最短路练习

0. Til the Cows Come Home  POJ - 2387

完美的模板题

 //#include<Windows.h>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<queue>
using namespace std;
const int MAX_V = ;
const int MAX_E = ;
const int inf = 0x3f3f3f3f; struct ENode
{
int to;
int Next;
int w;
};
ENode Edegs[MAX_E];
int Head[MAX_V];
int Dis[MAX_V];
int tnt;
void Add_ENode(int u, int v, int w)
{
++tnt;
Edegs[tnt].to = v;
Edegs[tnt].w = w;
Edegs[tnt].Next = Head[u];
Head[u] = tnt;
++tnt;
Edegs[tnt].to = u;
Edegs[tnt].w = w;
Edegs[tnt].Next = Head[v];
Head[v] = tnt;
}
struct cmpx
{
bool operator () (int &a, int &b) const
{
return Dis[a] - Dis[b] > ;
}
}; void Dijkstra(int x)
{
priority_queue<int, vector<int>, cmpx> q;
memset(Dis, inf, sizeof(Dis));
Dis[x] = ;
q.push(x);
while (!q.empty())
{
int u = q.top();
q.pop();
for (int k = Head[u]; k != -; k= Edegs[k].Next)
{
int v = Edegs[k].to;
if (Dis[v] > Dis[u] + Edegs[k].w)
{
Dis[v] = Dis[u] + Edegs[k].w;
q.push(v);
}
}
}
} int main()
{
int t, n;
cin >> t >> n;
tnt = -;
int a, b, w;
memset(Head, -, sizeof(Head));
for (int i = ; i < t; i++)
{
cin >> a >> b >> w;
Add_ENode(a, b, w);
}
Dijkstra();
cout << Dis[n] << endl;
// system("pause");
return ;
}

1. Frogger POJ - 2253

青蛙和石头。在池塘里有2只青蛙和n块石头,石头之间有一定距离,现在一只(腿短的)青蛙想要去找另一只青蛙yuehui;给出n块石头的坐标,1号为男主青蛙所在的石头,二号为目标石头。他想尽可能的省力,每次都跳的尽量短。问它在所有可行路径中单次跳跃需要的最长距离的最小值是多少?

 #include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<queue>
#include<cmath>
using namespace std;
const int MAX_V= ;
const double inf= 99999999999999999.0;
typedef pair<double, double> _pair;
_pair rock[MAX_V];
double get_dis(_pair a, _pair b)
{
return sqrt(((a.first- b.first)* (a.first- b.first) )+ ((a.second- b.second)* (a.second- b.second) ) );
}
double Dis[MAX_V];
struct cmpx
{
bool operator() (int &a, int &b) const
{
return Dis[a]- Dis[b]> ;
}
};
int Front[MAX_V];
void Dijkstra(int n)
{
priority_queue<int, vector<int>, cmpx> q;
fill(Dis, Dis+ n+ , inf);
//for(int i= 1; i<= n; i ++) printf("%f\n", Dis[2]);
Dis[]= ;
Front[]= -;
q.push();
while (! q.empty() )
{
int u= q.top();
q.pop();
for (int i= ; i<= n; i ++)
{
if (i== u) continue;
double detmp= get_dis(rock[u], rock[i]);
//printf("%f---%f---%f\n", Dis[u], detmp, Dis[i]);
if (Dis[i]> Dis[u]&& Dis[i]> detmp)
{
Dis[i]= max(Dis[u], detmp);
Front[i]= u;
q.push(i);
}
//printf("%f\n", Dis[i]);
}
}
}
int main()
{
int n;
int t= ;
while (cin >> n)
{
++ t;
if (n== ) break;
for (int i= ; i<= n; i ++)
{
cin >> rock[i].first >> rock[i].second;
}
//for(int i= 2; i<= n; i ++) printf("%f\n", get_dis(rock[1], rock[i]));
Dijkstra(n);
printf("Scenario #%d\n",t);
printf("Frog Distance = %.3f\n\n", Dis[]);
double ans= -1.0;
/*for (int c= n; c!= 1; c= Front[c])
{
double cnp= get_dis(rock[c], rock[Front[c]]);
ans= max(ans, cnp);
}
printf("Frog Distance = %.3f\n\n", ans);*/
}
return ;
}

2. Heavy Transportation POJ - 1797

城市中有N个路口,M个街道,每条街道都有最大承重限制;现在我们想要驾车从1号路口到N号路口,那么运输车所允许的最大重量是多少?

(不知道为什么老是PE,懒得改了)

 #include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<queue>
using namespace std;
const int maxv= ;
const int maxe= ;
const int inf= 0x3f3f3f3f; struct ENode
{
int to;
int w;
int Next;
};
ENode edegs[maxe];
int Head[maxv], tnt;
void init()
{
memset(Head, -, sizeof(Head));
tnt= -;
}
void Add_ENode(int a, int b, int w)
{
++ tnt;
edegs[tnt].to= b;
edegs[tnt].w= w;
edegs[tnt].Next= Head[a];
Head[a]= tnt;
++ tnt;
edegs[tnt].to= a;
edegs[tnt].w= w;
edegs[tnt].Next= Head[b];
Head[b]= tnt;
} int dis[maxv];
struct cmpx
{
bool operator() (int &a, int &b) const
{
return dis[a]- dis[b]< ;
}
};
void Dijkstra(int x)
{
priority_queue<int, vector<int>, cmpx> q;
memset(dis, , sizeof(dis));
dis[x]= inf;
q.push(x); while (! q.empty())
{
int u= q.top();
q.pop();
for (int k= Head[u]; k!= -; k= edegs[k].Next)
{
int v= edegs[k].to;
if (dis[v]< min(dis[u], edegs[k].w))
{
dis[v]= min(dis[u], edegs[k].w);
q.push(v);
}
}
}
} int main()
{
int t, Case= ;
int n, m;
scanf("%d", &t);
while (t --)
{
++ Case;
scanf("%d %d", &n, &m);
init();
int a, b, w;
for (int i= ; i< m; i ++)
{
scanf("%d %d %d", &a, &b, &w);
Add_ENode(a, b, w);
}
Dijkstra();
printf("Scenario #%d:\n%d\n", Case, dis[n]);
}
return ;
}

3. Travel (The 2019 ACM-ICPC China Shannxi Provincial Programming Contest M)  /**计蒜客复现赛:点这里*/

星系中有n 个星球,编号从1 到N。星球之间有M个隧道相连,每个隧道都有一个长度。你有一个航天器,航天器有两个属性:传输距离d 和传输次数e 。航天器只能通过短于或等于其传输距离的通道;如果传输次数耗尽,则无法再使用航天器。航天器具有等级,lv0的航天器d 和e 都等于0,你可以给你的航天器升级,每次升级都会消耗c 点花费,给你的航天器提升dx和 ex点属性。现在,告诉你n,m,m条通道的信息,还有给你的航天器升级时的c,dx,ex。

Q: 你能求出从1 到N 的最小花费吗?

A: 把原本记录到达此点最短距离的Dis[] 变成 记录到达此点所需要飞行器最低等级的Dis_Level[],这样剩下的就是普通的Dijkstra了。

 #include<algorithm>
#include<cstring>
#include<cstdio>
#include<queue>
using namespace std;
const int MAX_V= ;
const int MAX_E= ;
const int inf= 0x3f3f3f3f; struct ENode
{
int to;
int w;
int Next;
};
ENode edegs[MAX_E];
int Head[MAX_V], tnt;
void Add_ENode(int a, int b, int w)
{
edegs[++ tnt].to= b;
edegs[tnt].w= w;
edegs[tnt].Next= Head[a];
Head[a]= tnt;
edegs[++ tnt].to= a;
edegs[tnt].w= w;
edegs[tnt].Next= Head[b];
Head[b]= tnt;
} int Dis_Level[MAX_V]; //到每个点,所需要的飞船最小等级;
int deep[MAX_V]; //每个点bfs 的深度;
struct cmpx
{
bool operator() (int &a, int &b) const
{
return Dis_Level[a]- Dis_Level[b]> ;
}
};
void Dijkstra(int x, int _dis, int _cost)
{
/*x为起点, _dis是每次升级提升的传送距离, _cost是升级提升的传送次数;*/
memset(Dis_Level, inf, sizeof(Dis_Level));
memset(deep, inf, sizeof(deep));
priority_queue<int, vector<int>, cmpx> q;
Dis_Level[x]= ; //起点的飞行器等级为0;
deep[x]= ; //起点深度为0;
q.push(x);
while (! q.empty())
{
int u= q.top();
q.pop();
for (int k= Head[u]; k!= -; k= edegs[k].Next)
{
int v= edegs[k].to;
int lev_tmp= Dis_Level[u];
while (lev_tmp* _dis< edegs[k].w|| lev_tmp* _cost< deep[u]+ )
{
/*若当前的飞行器等级不能穿越此隧道,或传送次数已用完,则升级飞行器一次;*/
lev_tmp ++;
}
if (lev_tmp< Dis_Level[v])
{
/*如果此时的飞行器等级小与之前到达点v 的飞行器等级,则更新Dis_Level[v]*/
Dis_Level[v]= lev_tmp;
deep[v]= deep[u]+ ; //深度也要 +1;
q.push(v); //加入队列;
}
}
}
}
void into()
{
memset(Head, -, sizeof(Head));
tnt= -;
} int main()
{
int n, m;
int c, d, e;
int a, b ,w;
while (~ scanf("%d %d", &n, &m))
{
scanf("%d %d %d", &c, &d, &e);
into();
for (int i= ;i< m;i ++)
{
scanf("%d %d %d", &a, &b, &w);
Add_ENode(a, b, w);
}
Dijkstra(, d, e);
if (Dis_Level[n]== inf) printf("-1\n");
else printf("%lld\n", (long long)Dis_Level[n]* c);
}
return ;
}

4.Marriage Match IV (HDU 3416)

Starvae在A市,女孩在B市。每次starvae都可以到达B市并与他喜欢的女孩一起xoxo。但是他面前有两个问题,一是starvae必须在最短的时间内到达B,所以说他必须选择最短的路径;二是每条道路只能走一次,但每座城市他可以经过多次。那么,请你告诉他:从A-->B的(完全不同的)最短路径一共有几条?

Ps:最短路径+最大流。先用Dijkstra求出A到B的最短路径并处理dis[]数组,然后依照条件(dis[v]== dis[u]+ edegs[k].w)找出所有在最短路径上的边,并建一个图2。随后就是Dinic跑最大流出结果,代码如下。

 #include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<queue>
using namespace std;
const int maxv= ;
const int maxe= ;
const int inf= 0x3f3f3f3f; struct ENode
{
int to;
int w;
int Next;
};
ENode edegs[maxe];
int Head[maxv], tnt;
void init()
{
memset(Head, -, sizeof(Head));
tnt= -;
}
void Add_ENode(int a, int b, int w)
{
++ tnt;
edegs[tnt].to= b;
edegs[tnt].w= w;
edegs[tnt].Next= Head[a];
Head[a]= tnt;
} int dis[maxv];
struct cmpx
{
bool operator() (int &a, int &b) const
{
return dis[a]- dis[b]> ;
}
};
void Dijkstra(int x)
{
priority_queue<int, vector<int>, cmpx> q;
memset(dis, inf, sizeof(dis));
dis[x]= ;
q.push(x); while (! q.empty())
{
int u= q.top();
q.pop(); for (int k= Head[u]; k!= -; k= edegs[k].Next)
{
int v= edegs[k].to;
if (dis[v]> dis[u]+ edegs[k].w )
{
dis[v]= dis[u]+ edegs[k].w;
q.push(v);
}
}
}
} /*建新图,跑最大流*/
ENode edegs1[maxe];
int Head1[maxv], tnt1;
void init1()
{
memset(Head1, -, sizeof(Head1));
tnt1= -;
}
void Add_ENode1(int a, int b, int w)
{
++ tnt1;
edegs1[tnt1].to= b;
edegs1[tnt1].w= w;
edegs1[tnt1].Next= Head1[a];
Head1[a]= tnt1;
++ tnt1;
edegs1[tnt1].to= a;
edegs1[tnt1].w= ;
edegs1[tnt1].Next= Head1[b];
Head1[b]= tnt1;
}
void Dijk2(int n)
{
init1();
for (int u= ; u<= n; u ++)
{
for (int k= Head[u]; k!= -; k= edegs[k].Next)
{
int v= edegs[k].to;
if (dis[v]== dis[u]+ edegs[k].w )
{
Add_ENode1(u, v, );
}
}
}
}
int level[maxv];
bool bfs_level (int s, int t)
{
memset(level, -, sizeof(level)); //所有点的等级初始化为-1;
level[s]= ; //源点的等级为1;
int que[maxv]; //队列que:按序保存已搜索到的点;
int iq= ;
que[iq ++]= s; //先将源点s 加入队列;
for (int i= ; i< iq; i ++)
{
int u= que[i]; //取出队首元素;
if (u== t)
{
/*找到汇点t,返回*/
return true;
}
for (int k= Head1[u]; k!= -; k= edegs1[k].Next)
{
/*遍历,查找到之前未找到的、可抵达的点便加入队列*/
int v= edegs1[k].to;
if (-== level[v]&& edegs1[k].w)
{
level[v]= level[u]+ ; //深度 +1;
que[iq ++]= v;
}
}
}
return false;
}
int dfs(int now, int c_max, int t)
{
/**DFS 实现多路增广*/
/*now:起点;c_max:从源点s到节点now的最大流量;t:汇点、dfs结束的终点*/
if (now== t) return c_max; //当now== t时,c_max便是要求的最大流;
int ret= , f;
for (int k= Head1[now]; k!= -; k= edegs1[k].Next)
{
if (edegs1[k].w&& level[edegs1[k] .to]== level[now]+ )
{
/**/
f= dfs(edegs1[k].to, min(c_max- ret, edegs1[k].w), t);
edegs1[k].w-= f;
edegs1[k^].w+= f;
ret+= f;
if(ret== c_max) return ret;
}
}
return ret;
}
int dinic(int s, int t)
{
int ans= ;
while(bfs_level(s, t))
{
ans+= dfs(s, inf, t);
}
return ans;
} int main()
{
int t;
int n, m;
scanf("%d", &t);
while (t --)
{
scanf("%d %d", &n, &m);
init();
int a, b, w;
for (int i= ; i< m; i ++)
{
scanf("%d %d %d", &a, &b, &w);
Add_ENode(a, b, w);
}
int start, endd;
scanf("%d %d", &start, &endd);
Dijkstra(start);
Dijk2(n);
int ans= dinic(start, endd);
printf("%d\n", ans);
}
return ;
}

end;

专题训练——[kuangbin带你飞]最短路练习的更多相关文章

  1. kuangbin带你飞 最短路 题解

    求一个图最短路边的办法.好像下面的那个有问题.单向边和双向边一定是有区别的.这个比较容易.参照该文的最短路网络流题目和连通图题目一题求最短路关节边 另外上述2个题目的代码好像有问题. 在UVALIVE ...

  2. 「kuangbin带你飞」专题十七 AC自动机

    layout: post title: 「kuangbin带你飞」专题十七 AC自动机 author: "luowentaoaa" catalog: true tags: - ku ...

  3. [kuangbin带你飞]专题1-23题目清单总结

    [kuangbin带你飞]专题1-23 专题一 简单搜索 POJ 1321 棋盘问题POJ 2251 Dungeon MasterPOJ 3278 Catch That CowPOJ 3279 Fli ...

  4. 【算法系列学习三】[kuangbin带你飞]专题二 搜索进阶 之 A-Eight 反向bfs打表和康拓展开

    [kuangbin带你飞]专题二 搜索进阶 之 A-Eight 这是一道经典的八数码问题.首先,简单介绍一下八数码问题: 八数码问题也称为九宫问题.在3×3的棋盘,摆有八个棋子,每个棋子上标有1至8的 ...

  5. 「kuangbin带你飞」专题十四 数论基础

    layout: post title: 「kuangbin带你飞」专题十四 数论基础 author: "luowentaoaa" catalog: true tags: mathj ...

  6. 「kuangbin带你飞」专题二十 斜率DP

    layout: post title: 「kuangbin带你飞」专题二十 斜率DP author: "luowentaoaa" catalog: true tags: mathj ...

  7. 「kuangbin带你飞」专题二十二 区间DP

    layout: post title: 「kuangbin带你飞」专题二十二 区间DP author: "luowentaoaa" catalog: true tags: - ku ...

  8. 「kuangbin带你飞」专题十九 矩阵

    layout: post title: 「kuangbin带你飞」专题十九 矩阵 author: "luowentaoaa" catalog: true tags: mathjax ...

  9. 「kuangbin带你飞」专题十八 后缀数组

    layout: post title: 「kuangbin带你飞」专题十八 后缀数组 author: "luowentaoaa" catalog: true tags: - kua ...

随机推荐

  1. Java:目录

    ylbtech-Java:目录 1.返回顶部   2.返回顶部   3.返回顶部   4.返回顶部   5.返回顶部     6.返回顶部   作者:ylbtech出处:http://ylbtech. ...

  2. 使用 SQL Server Management Studio的活动和监视器 查看运行的SQL语句

    使用SQL Server Management Studio可以查看SQL Server 服务器执行的SQL语句,支持sql server,(LocalDB)\V11.0,Projects\v12和s ...

  3. Mac下Ruby升级与Rails的安装

    也是醉了,网上查了半天一脸懵逼.然后自己动手试试 gem install rails瞬间命令行就没反应了,以为命令行挂了,但是一会儿报错说是没有权限. 好吧,那么来这个 sudo gem instal ...

  4. bzoj 4849: [Neerc2016]Mole Tunnels【模拟费用流】

    参考:https://www.cnblogs.com/CQzhangyu/p/6952371.html 费用流很简单,考虑但是会T. 考虑费用流的本质,流一次需要要找一个能够从当前点到达的距离最小的点 ...

  5. bzoj 4898: [Apio2017]商旅【Floyd+分数规划+二分】

    其实并不会分数规划 因为要最大化 ans=总收益/总路程 ,所以考虑二分答案,找到一条 ans<=总收益/总路程 的回路.先预处理出d(i,j)为(i,j)最短路,w(i,j)为在i买某个物品在 ...

  6. 【API】反转输入字符(Java)

    请求输入字符, 输出反转. import java.util.Scanner; public class T01 { public static void main(String[] args) { ...

  7. 树上最长链 Farthest Nodes in a Tree LightOJ - 1094 && [ZJOI2007]捉迷藏 && 最长链

    树上最远点对(树的直径) 做法1:树形dp 最长路一定是经过树上的某一个节点的. 因此: an1[i],an2[i]分别表示一个点向下的最长链和次长链,次长链不存在就设为0:这两者很容易求 an3[i ...

  8. ACM_棋棋棋棋棋(规律题)

    棋棋棋棋棋 Time Limit: 2000/1000ms (Java/Others) Problem Description: 在遥远的K次元空间,一年一度的GDUFE-GAME又开始了.每年的GD ...

  9. 题解报告:hdu 1166 敌兵布阵(线段树or树状数组)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1166 Problem Description C国的死对头A国这段时间正在进行军事演习,所以C国间谍头 ...

  10. Java标识符的习惯命名规范

    1 常量标识符:全部用大写字母和下划线表示.如SALES_MAX 2 类名或接口名:标识符用大写字母开头.如CreditCard 3 变量名和方法名:以小写字母开头,单词之间不要有分隔符,第二 及后面 ...