#专题练习# 最短路练习
最短路练习
0. Til the Cows Come Home POJ - 2387
完美的模板题
1 //#include<Windows.h> 2 #include<iostream> 3 #include<algorithm> 4 #include<cstring> 5 #include<cstdio> 6 #include<queue> 7 using namespace std; 8 const int MAX_V = 10005; 9 const int MAX_E = 20010; 10 const int inf = 0x3f3f3f3f; 11 12 struct ENode 13 { 14 int to; 15 int Next; 16 int w; 17 }; 18 ENode Edegs[MAX_E]; 19 int Head[MAX_V]; 20 int Dis[MAX_V]; 21 int tnt; 22 void Add_ENode(int u, int v, int w) 23 { 24 ++tnt; 25 Edegs[tnt].to = v; 26 Edegs[tnt].w = w; 27 Edegs[tnt].Next = Head[u]; 28 Head[u] = tnt; 29 ++tnt; 30 Edegs[tnt].to = u; 31 Edegs[tnt].w = w; 32 Edegs[tnt].Next = Head[v]; 33 Head[v] = tnt; 34 } 35 struct cmpx 36 { 37 bool operator () (int &a, int &b) const 38 { 39 return Dis[a] - Dis[b] > 0; 40 } 41 }; 42 43 void Dijkstra(int x) 44 { 45 priority_queue<int, vector<int>, cmpx> q; 46 memset(Dis, inf, sizeof(Dis)); 47 Dis[x] = 0; 48 q.push(x); 49 while (!q.empty()) 50 { 51 int u = q.top(); 52 q.pop(); 53 for (int k = Head[u]; k != -1; k= Edegs[k].Next) 54 { 55 int v = Edegs[k].to; 56 if (Dis[v] > Dis[u] + Edegs[k].w) 57 { 58 Dis[v] = Dis[u] + Edegs[k].w; 59 q.push(v); 60 } 61 } 62 } 63 } 64 65 int main() 66 { 67 int t, n; 68 cin >> t >> n; 69 tnt = -1; 70 int a, b, w; 71 memset(Head, -1, sizeof(Head)); 72 for (int i = 0; i < t; i++) 73 { 74 cin >> a >> b >> w; 75 Add_ENode(a, b, w); 76 } 77 Dijkstra(1); 78 cout << Dis[n] << endl; 79 // system("pause"); 80 return 0; 81 }
1. Frogger POJ - 2253
青蛙和石头。在池塘里有2只青蛙和n块石头,石头之间有一定距离,现在一只(腿短的)青蛙想要去找另一只青蛙yuehui;给出n块石头的坐标,1号为男主青蛙所在的石头,二号为目标石头。他想尽可能的省力,每次都跳的尽量短。问它在所有可行路径中单次跳跃需要的最长距离的最小值是多少?
1 #include<iostream> 2 #include<algorithm> 3 #include<cstring> 4 #include<cstdio> 5 #include<queue> 6 #include<cmath> 7 using namespace std; 8 const int MAX_V= 210; 9 const double inf= 99999999999999999.0; 10 typedef pair<double, double> _pair; 11 _pair rock[MAX_V]; 12 double get_dis(_pair a, _pair b) 13 { 14 return sqrt(((a.first- b.first)* (a.first- b.first) )+ ((a.second- b.second)* (a.second- b.second) ) ); 15 } 16 double Dis[MAX_V]; 17 struct cmpx 18 { 19 bool operator() (int &a, int &b) const 20 { 21 return Dis[a]- Dis[b]> 0; 22 } 23 }; 24 int Front[MAX_V]; 25 void Dijkstra(int n) 26 { 27 priority_queue<int, vector<int>, cmpx> q; 28 fill(Dis, Dis+ n+ 1, inf); 29 //for(int i= 1; i<= n; i ++) printf("%f\n", Dis[2]); 30 Dis[1]= 0; 31 Front[1]= -1; 32 q.push(1); 33 while (! q.empty() ) 34 { 35 int u= q.top(); 36 q.pop(); 37 for (int i= 2; i<= n; i ++) 38 { 39 if (i== u) continue; 40 double detmp= get_dis(rock[u], rock[i]); 41 //printf("%f---%f---%f\n", Dis[u], detmp, Dis[i]); 42 if (Dis[i]> Dis[u]&& Dis[i]> detmp) 43 { 44 Dis[i]= max(Dis[u], detmp); 45 Front[i]= u; 46 q.push(i); 47 } 48 //printf("%f\n", Dis[i]); 49 } 50 } 51 } 52 int main() 53 { 54 int n; 55 int t= 0; 56 while (cin >> n) 57 { 58 ++ t; 59 if (n== 0) break; 60 for (int i= 1; i<= n; i ++) 61 { 62 cin >> rock[i].first >> rock[i].second; 63 } 64 //for(int i= 2; i<= n; i ++) printf("%f\n", get_dis(rock[1], rock[i])); 65 Dijkstra(n); 66 printf("Scenario #%d\n",t); 67 printf("Frog Distance = %.3f\n\n", Dis[2]); 68 double ans= -1.0; 69 /*for (int c= n; c!= 1; c= Front[c]) 70 { 71 double cnp= get_dis(rock[c], rock[Front[c]]); 72 ans= max(ans, cnp); 73 } 74 printf("Frog Distance = %.3f\n\n", ans);*/ 75 } 76 return 0; 77 }
2. Heavy Transportation POJ - 1797
城市中有N个路口,M个街道,每条街道都有最大承重限制;现在我们想要驾车从1号路口到N号路口,那么运输车所允许的最大重量是多少?
(不知道为什么老是PE,懒得改了)
1 #include<algorithm> 2 #include<iostream> 3 #include<cstring> 4 #include<cstdio> 5 #include<queue> 6 using namespace std; 7 const int maxv= 100010; 8 const int maxe= 2100010; 9 const int inf= 0x3f3f3f3f; 10 11 struct ENode 12 { 13 int to; 14 int w; 15 int Next; 16 }; 17 ENode edegs[maxe]; 18 int Head[maxv], tnt; 19 void init() 20 { 21 memset(Head, -1, sizeof(Head)); 22 tnt= -1; 23 } 24 void Add_ENode(int a, int b, int w) 25 { 26 ++ tnt; 27 edegs[tnt].to= b; 28 edegs[tnt].w= w; 29 edegs[tnt].Next= Head[a]; 30 Head[a]= tnt; 31 ++ tnt; 32 edegs[tnt].to= a; 33 edegs[tnt].w= w; 34 edegs[tnt].Next= Head[b]; 35 Head[b]= tnt; 36 } 37 38 int dis[maxv]; 39 struct cmpx 40 { 41 bool operator() (int &a, int &b) const 42 { 43 return dis[a]- dis[b]< 0; 44 } 45 }; 46 void Dijkstra(int x) 47 { 48 priority_queue<int, vector<int>, cmpx> q; 49 memset(dis, 0, sizeof(dis)); 50 dis[x]= inf; 51 q.push(x); 52 53 while (! q.empty()) 54 { 55 int u= q.top(); 56 q.pop(); 57 for (int k= Head[u]; k!= -1; k= edegs[k].Next) 58 { 59 int v= edegs[k].to; 60 if (dis[v]< min(dis[u], edegs[k].w)) 61 { 62 dis[v]= min(dis[u], edegs[k].w); 63 q.push(v); 64 } 65 } 66 } 67 } 68 69 int main() 70 { 71 int t, Case= 0; 72 int n, m; 73 scanf("%d", &t); 74 while (t --) 75 { 76 ++ Case; 77 scanf("%d %d", &n, &m); 78 init(); 79 int a, b, w; 80 for (int i= 0; i< m; i ++) 81 { 82 scanf("%d %d %d", &a, &b, &w); 83 Add_ENode(a, b, w); 84 } 85 Dijkstra(1); 86 printf("Scenario #%d:\n%d\n", Case, dis[n]); 87 } 88 return 0; 89 }
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了。
1 #include<algorithm> 2 #include<cstring> 3 #include<cstdio> 4 #include<queue> 5 using namespace std; 6 const int MAX_V= 100010; 7 const int MAX_E= 400010; 8 const int inf= 0x3f3f3f3f; 9 10 struct ENode 11 { 12 int to; 13 int w; 14 int Next; 15 }; 16 ENode edegs[MAX_E]; 17 int Head[MAX_V], tnt; 18 void Add_ENode(int a, int b, int w) 19 { 20 edegs[++ tnt].to= b; 21 edegs[tnt].w= w; 22 edegs[tnt].Next= Head[a]; 23 Head[a]= tnt; 24 edegs[++ tnt].to= a; 25 edegs[tnt].w= w; 26 edegs[tnt].Next= Head[b]; 27 Head[b]= tnt; 28 } 29 30 int Dis_Level[MAX_V]; //到每个点,所需要的飞船最小等级; 31 int deep[MAX_V]; //每个点bfs 的深度; 32 struct cmpx 33 { 34 bool operator() (int &a, int &b) const 35 { 36 return Dis_Level[a]- Dis_Level[b]> 0; 37 } 38 }; 39 void Dijkstra(int x, int _dis, int _cost) 40 { 41 /*x为起点, _dis是每次升级提升的传送距离, _cost是升级提升的传送次数;*/ 42 memset(Dis_Level, inf, sizeof(Dis_Level)); 43 memset(deep, inf, sizeof(deep)); 44 priority_queue<int, vector<int>, cmpx> q; 45 Dis_Level[x]= 0; //起点的飞行器等级为0; 46 deep[x]= 0; //起点深度为0; 47 q.push(x); 48 while (! q.empty()) 49 { 50 int u= q.top(); 51 q.pop(); 52 for (int k= Head[u]; k!= -1; k= edegs[k].Next) 53 { 54 int v= edegs[k].to; 55 int lev_tmp= Dis_Level[u]; 56 while (lev_tmp* _dis< edegs[k].w|| lev_tmp* _cost< deep[u]+ 1) 57 { 58 /*若当前的飞行器等级不能穿越此隧道,或传送次数已用完,则升级飞行器一次;*/ 59 lev_tmp ++; 60 } 61 if (lev_tmp< Dis_Level[v]) 62 { 63 /*如果此时的飞行器等级小与之前到达点v 的飞行器等级,则更新Dis_Level[v]*/ 64 Dis_Level[v]= lev_tmp; 65 deep[v]= deep[u]+ 1; //深度也要 +1; 66 q.push(v); //加入队列; 67 } 68 } 69 } 70 } 71 void into() 72 { 73 memset(Head, -1, sizeof(Head)); 74 tnt= -1; 75 } 76 77 int main() 78 { 79 int n, m; 80 int c, d, e; 81 int a, b ,w; 82 while (~ scanf("%d %d", &n, &m)) 83 { 84 scanf("%d %d %d", &c, &d, &e); 85 into(); 86 for (int i= 0;i< m;i ++) 87 { 88 scanf("%d %d %d", &a, &b, &w); 89 Add_ENode(a, b, w); 90 } 91 Dijkstra(1, d, e); 92 if (Dis_Level[n]== inf) printf("-1\n"); 93 else printf("%lld\n", (long long)Dis_Level[n]* c); 94 } 95 return 0; 96 }
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跑最大流出结果,代码如下。
1 #include<algorithm> 2 #include<iostream> 3 #include<cstring> 4 #include<cstdio> 5 #include<queue> 6 using namespace std; 7 const int maxv= 1010; 8 const int maxe= 400010; 9 const int inf= 0x3f3f3f3f; 10 11 struct ENode 12 { 13 int to; 14 int w; 15 int Next; 16 }; 17 ENode edegs[maxe]; 18 int Head[maxv], tnt; 19 void init() 20 { 21 memset(Head, -1, sizeof(Head)); 22 tnt= -1; 23 } 24 void Add_ENode(int a, int b, int w) 25 { 26 ++ tnt; 27 edegs[tnt].to= b; 28 edegs[tnt].w= w; 29 edegs[tnt].Next= Head[a]; 30 Head[a]= tnt; 31 } 32 33 int dis[maxv]; 34 struct cmpx 35 { 36 bool operator() (int &a, int &b) const 37 { 38 return dis[a]- dis[b]> 0; 39 } 40 }; 41 void Dijkstra(int x) 42 { 43 priority_queue<int, vector<int>, cmpx> q; 44 memset(dis, inf, sizeof(dis)); 45 dis[x]= 0; 46 q.push(x); 47 48 while (! q.empty()) 49 { 50 int u= q.top(); 51 q.pop(); 52 53 for (int k= Head[u]; k!= -1; k= edegs[k].Next) 54 { 55 int v= edegs[k].to; 56 if (dis[v]> dis[u]+ edegs[k].w ) 57 { 58 dis[v]= dis[u]+ edegs[k].w; 59 q.push(v); 60 } 61 } 62 } 63 } 64 65 /*建新图,跑最大流*/ 66 ENode edegs1[maxe]; 67 int Head1[maxv], tnt1; 68 void init1() 69 { 70 memset(Head1, -1, sizeof(Head1)); 71 tnt1= -1; 72 } 73 void Add_ENode1(int a, int b, int w) 74 { 75 ++ tnt1; 76 edegs1[tnt1].to= b; 77 edegs1[tnt1].w= w; 78 edegs1[tnt1].Next= Head1[a]; 79 Head1[a]= tnt1; 80 ++ tnt1; 81 edegs1[tnt1].to= a; 82 edegs1[tnt1].w= 0; 83 edegs1[tnt1].Next= Head1[b]; 84 Head1[b]= tnt1; 85 } 86 void Dijk2(int n) 87 { 88 init1(); 89 for (int u= 1; u<= n; u ++) 90 { 91 for (int k= Head[u]; k!= -1; k= edegs[k].Next) 92 { 93 int v= edegs[k].to; 94 if (dis[v]== dis[u]+ edegs[k].w ) 95 { 96 Add_ENode1(u, v, 1); 97 } 98 } 99 } 100 } 101 int level[maxv]; 102 bool bfs_level (int s, int t) 103 { 104 memset(level, -1, sizeof(level)); //所有点的等级初始化为-1; 105 level[s]= 1; //源点的等级为1; 106 int que[maxv]; //队列que:按序保存已搜索到的点; 107 int iq= 0; 108 que[iq ++]= s; //先将源点s 加入队列; 109 for (int i= 0; i< iq; i ++) 110 { 111 int u= que[i]; //取出队首元素; 112 if (u== t) 113 { 114 /*找到汇点t,返回*/ 115 return true; 116 } 117 for (int k= Head1[u]; k!= -1; k= edegs1[k].Next) 118 { 119 /*遍历,查找到之前未找到的、可抵达的点便加入队列*/ 120 int v= edegs1[k].to; 121 if (-1== level[v]&& edegs1[k].w) 122 { 123 level[v]= level[u]+ 1; //深度 +1; 124 que[iq ++]= v; 125 } 126 } 127 } 128 return false; 129 } 130 int dfs(int now, int c_max, int t) 131 { 132 /**DFS 实现多路增广*/ 133 /*now:起点;c_max:从源点s到节点now的最大流量;t:汇点、dfs结束的终点*/ 134 if (now== t) return c_max; //当now== t时,c_max便是要求的最大流; 135 int ret= 0, f; 136 for (int k= Head1[now]; k!= -1; k= edegs1[k].Next) 137 { 138 if (edegs1[k].w&& level[edegs1[k] .to]== level[now]+ 1) 139 { 140 /**/ 141 f= dfs(edegs1[k].to, min(c_max- ret, edegs1[k].w), t); 142 edegs1[k].w-= f; 143 edegs1[k^1].w+= f; 144 ret+= f; 145 if(ret== c_max) return ret; 146 } 147 } 148 return ret; 149 } 150 int dinic(int s, int t) 151 { 152 int ans= 0; 153 while(bfs_level(s, t)) 154 { 155 ans+= dfs(s, inf, t); 156 } 157 return ans; 158 } 159 160 int main() 161 { 162 int t; 163 int n, m; 164 scanf("%d", &t); 165 while (t --) 166 { 167 scanf("%d %d", &n, &m); 168 init(); 169 int a, b, w; 170 for (int i= 0; i< m; i ++) 171 { 172 scanf("%d %d %d", &a, &b, &w); 173 Add_ENode(a, b, w); 174 } 175 int start, endd; 176 scanf("%d %d", &start, &endd); 177 Dijkstra(start); 178 Dijk2(n); 179 int ans= dinic(start, endd); 180 printf("%d\n", ans); 181 } 182 return 0; 183 }
end;