最近在刷郏老大博客上的最短路专题
【HDU】
1548 A strange lift 基础最短路(或bfs)
1 //#define LOCAL 2 #include <iostream> 3 #include <cstdio> 4 #include <cstring> 5 using namespace std; 6 7 const int maxn = 200 + 10; 8 struct Point 9 { 10 int h; 11 int times; 12 }qu[maxn]; 13 int n, from, to, go[maxn], vis[maxn]; 14 int head, tail; 15 int dir[2] = {1, -1}; 16 17 void BFS(void) 18 { 19 head = 0, tail = 1; 20 qu[0].h = from, qu[0].times = 0; 21 while(head < tail) 22 { 23 if(qu[head].h == to) 24 { 25 printf("%d\n", qu[head].times); 26 return; 27 } 28 for(int i = 0; i < 2; ++i) 29 { 30 int hh = qu[head].h + go[qu[head].h]*dir[i]; 31 if(hh>0 && hh<=n && (!vis[hh])) 32 { 33 vis[hh] = 1; 34 qu[tail].h = hh; 35 qu[tail++].times = qu[head].times + 1; 36 } 37 } 38 ++head; 39 } 40 printf("-1\n"); 41 } 42 43 int main(void) 44 { 45 #ifdef LOCAL 46 freopen("1548in.txt", "r", stdin); 47 #endif 48 49 while(scanf("%d", &n) == 1 && n) 50 { 51 scanf("%d%d", &from, &to); 52 for(int i = 1; i <= n; ++i) 53 scanf("%d", &go[i]); 54 memset(vis, 0, sizeof(vis)); 55 BFS(); 56 } 57 return 0; 58 }
2544 最短路 基础最短路
1 #include <cstdio> 2 #include <cstring> 3 #include <vector> 4 #include <queue> 5 #include <algorithm> 6 #include <map> 7 #define MP make_pair 8 using namespace std; 9 10 typedef pair<int, int> PII; 11 12 const int maxn = 100 + 10; 13 const int INF = 1000000000; 14 15 struct Edge 16 { 17 int from, to, dist; 18 Edge(int u, int v, int d):from(u), to(v), dist(d) {} 19 }; 20 21 int n, m; 22 int d[maxn]; 23 vector<Edge> edges; 24 vector<int> G[maxn]; 25 bool done[maxn]; 26 27 void init() 28 { 29 for(int i = 1; i <= n; i++) G[i].clear(); 30 edges.clear(); 31 } 32 33 void AddEdge(int from, int to, int dist) 34 { 35 edges.push_back(Edge(from, to, dist)); 36 int sz = edges.size(); 37 G[from].push_back(sz - 1); 38 } 39 40 void dijkstra() 41 { 42 memset(done, false, sizeof(done)); 43 d[0] = 0; 44 for(int i = 2; i <= n; i++) d[i] = INF; 45 priority_queue<PII, vector<PII>, greater<PII> > Q; 46 Q.push(MP(0, 1)); 47 while(!Q.empty()) 48 { 49 PII x = Q.top(); Q.pop(); 50 int u = x.second; 51 if(done[u]) continue; 52 done[u] = true; 53 for(int i = 0; i < G[u].size(); i++) 54 { 55 Edge& e = edges[G[u][i]]; 56 if(d[e.to] > d[u] + e.dist) 57 { 58 d[e.to] = d[u] + e.dist; 59 Q.push(MP(d[e.to], e.to)); 60 } 61 } 62 } 63 } 64 65 int main() 66 { 67 while(scanf("%d%d", &n, &m) == 2) 68 { 69 if(n == 0 && m == 0) break; 70 71 init(); 72 int u, v, d; 73 while( m-- ) { scanf("%d%d%d", &u, &v, &d); AddEdge(u, v, d); AddEdge(v, u, d); } 74 dijkstra(); 75 printf("%d\n", ::d[n]); 76 } 77 78 return 0; 79 }
3790 最短路径问题 最短路径上的最小花费
在进行松弛操作的时候顺便记录下最小花费即可
另外:注意重边
1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 using namespace std; 5 6 const int maxn = 1000 + 10; 7 const int INF = 1000000000; 8 int n, m, s, t; 9 int G[maxn][maxn], P[maxn][maxn]; 10 int d[maxn], p[maxn]; 11 bool done[maxn]; 12 13 void init() 14 { 15 for(int i = 1; i <= n; i++) 16 for(int j = 1; j <= n; j++) 17 G[i][j] = P[i][j] = INF; 18 } 19 20 void dijkstra() 21 { 22 for(int i = 1; i <= n; i++) d[i] = p[i] = INF; 23 d[s] = p[s] = 0; 24 memset(done, false, sizeof(done)); 25 for(int i = 1; i <= n; i++) 26 { 27 int m = INF, x; 28 for(int y = 1; y <= n; y++) if(!done[y] && d[y] <= m) m = d[x = y]; 29 done[x] = true; 30 for(int y = 1; y <= n; y++) 31 { 32 if(d[y] > d[x] + G[x][y]) 33 { 34 d[y] = d[x] + G[x][y]; 35 p[y] = p[x] + P[x][y]; 36 } 37 else if(d[y] == d[x] + G[x][y] && p[y] > p[x] + P[x][y]) 38 p[y] = p[x] + P[x][y]; 39 } 40 } 41 } 42 43 int main() 44 { 45 while(scanf("%d%d", &n, &m) == 2) 46 { 47 if(!n && !m) break; 48 49 init(); 50 int u, v, dist, price; 51 while( m-- ) 52 { 53 scanf("%d%d%d%d", &u, &v, &dist, &price); 54 if(G[u][v] > dist) 55 { 56 G[u][v] = G[v][u] = dist; 57 P[u][v] = P[v][u] = price; 58 } 59 else if(G[u][v] == dist && P[u][v] > price) 60 P[u][v] = P[v][u] = price; 61 } 62 scanf("%d%d", &s, &t); 63 64 dijkstra(); 65 printf("%d %d\n", d[t], p[t]); 66 } 67 68 return 0; 69 }
2066 一个人的旅行 多源多汇,其实和普通最短路并没有什么变化
同样要注意重边,除非后面的题明确说明没有重边,否则都要考虑这个问题
1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 using namespace std; 5 6 const int maxn = 1000 + 10; 7 const int INF = 1000000000; 8 9 int n, m, S, T, s[maxn], t[maxn]; 10 int G[maxn][maxn]; 11 int d[maxn]; 12 bool done[maxn]; 13 14 void init() 15 { 16 memset(G, 0x3f, sizeof(G)); 17 } 18 19 void dijkstra() 20 { 21 memset(done, false, sizeof(done)); 22 for(int i = 1; i <= n; i++) d[i] = INF; 23 for(int i = 0; i < S; i++) d[s[i]] = 0; 24 for(int i = 1; i <= n; i++) 25 { 26 int m = INF, x; 27 for(int y = 1; y <= n; y++) if(!done[y] && d[y] <= m) m = d[x = y]; 28 done[x] = true; 29 for(int y = 1; y <= n; y++) 30 if(d[y] > d[x] + G[x][y]) d[y] = d[x] + G[x][y]; 31 } 32 } 33 34 int main() 35 { 36 while(scanf("%d%d%d", &m, &S, &T) == 3) 37 { 38 init(); 39 n = 1; 40 while( m-- ) 41 { 42 int u, v, dist; 43 scanf("%d%d%d", &u, &v, &dist); 44 if(G[u][v] > dist) G[u][v] = G[v][u] = dist; 45 n = max(n, max(u, v)); 46 } 47 for(int i = 0; i < S; i++) { scanf("%d", s + i); n = max(n, s[i]); } 48 for(int i = 0; i < T; i++) { scanf("%d", t + i); n = max(n, t[i]); } 49 50 dijkstra(); 51 int ans = INF; 52 for(int i = 0; i < T; i++) ans = min(ans, d[t[i]]); 53 printf("%d\n", ans); 54 } 55 56 return 0; 57 }
2112 HDU Today 基础最短路
可以用个map对地名进行编号
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <string> 5 #include <map> 6 using namespace std; 7 8 int n, tot, s, t; 9 const int maxn = 150 + 10; 10 const int INF = 1000000000; 11 int G[maxn][maxn]; 12 int d[maxn]; 13 bool done[maxn]; 14 15 map<string, int> id; 16 17 void init() 18 { 19 memset(G, 0x3f, sizeof(G)); 20 id.clear(); 21 tot = 1; 22 } 23 24 int ID(string s) 25 { 26 if(!id.count(s)) id[s] = tot++; 27 return id[s]; 28 } 29 30 void dijkstra() 31 { 32 memset(done, false, sizeof(done)); 33 for(int i = 1; i < tot; i++) d[i] = INF; 34 d[s] = 0; 35 for(int i = 1; i < tot; i++) 36 { 37 int m = INF, x; 38 for(int y = 1; y < tot; y++) if(!done[y] && d[y] <= m) m = d[x = y]; 39 done[x] = true; 40 for(int y = 1; y < tot; y++) d[y] = min(d[y], d[x] + G[x][y]); 41 } 42 } 43 44 int main() 45 { 46 while(scanf("%d", &n) == 1 && n + 1) 47 { 48 init(); 49 string st, ed; 50 cin >> st >> ed; 51 s = ID(st), t = ID(ed); 52 while( n-- ) 53 { 54 cin >> st >> ed; 55 int dist; scanf("%d", &dist); 56 int u = ID(st); 57 int v = ID(ed); 58 if(G[u][v] > dist) G[u][v] = G[v][u] = dist; 59 } 60 61 dijkstra(); 62 printf("%d\n", d[t] == INF ? -1 : d[t]); 63 } 64 65 return 0; 66 }
1874 畅通工程续 基础最短路
1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 using namespace std; 5 6 const int maxn = 200 + 10; 7 const int INF = 0x3f3f3f3f; 8 int n, m, s, t; 9 10 int G[maxn][maxn]; 11 int d[maxn]; 12 bool done[maxn]; 13 14 void dijkstra() 15 { 16 memset(d, 0x3f, sizeof(d)); 17 d[s] = 0; 18 memset(done, false, sizeof(done)); 19 for(int i = 0; i < n; i++) 20 { 21 int m = INF, x; 22 for(int y = 0; y < n; y++) if(!done[y] && d[y] <= m) m = d[x = y]; 23 done[x] = true; 24 for(int y = 0; y < n; y++) d[y] = min(d[y], d[x] + G[x][y]); 25 } 26 } 27 28 int main() 29 { 30 while(scanf("%d%d", &n, &m) == 2) 31 { 32 memset(G, 0x3f, sizeof(G)); 33 while( m-- ) 34 { 35 int u, v, dist; 36 scanf("%d%d%d", &u, &v, &dist); 37 if(G[u][v] > dist) G[u][v] = G[v][u] = dist; 38 } 39 scanf("%d%d", &s, &t); 40 dijkstra(); 41 printf("%d\n", d[t] == INF ? -1 : d[t]); 42 } 43 44 return 0; 45 }
1217 Arbitrage 货币交换 Floyd求最大的兑换比率
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <string> 5 #include <algorithm> 6 #include <map> 7 using namespace std; 8 9 const int maxn = 30 + 10; 10 int n, m; 11 double d[maxn][maxn]; 12 map<string, int> id; 13 14 void init() 15 { 16 id.clear(); 17 memset(d, 0, sizeof(d)); 18 for(int i = 0; i < n; i++) d[i][i] = 1; 19 } 20 21 void floyd() 22 { 23 for(int i = 0; i < n; i++) 24 for(int j = 0; j < n; j++) 25 for(int k = 0; k < n; k++) 26 d[i][j] = max(d[i][j], d[i][k] * d[k][j]); 27 } 28 29 int main() 30 { 31 int kase = 0; 32 while(scanf("%d", &n) == 1 && n) 33 { 34 init(); 35 string s1, s2; 36 for(int i = 0; i < n; i++) { cin >> s1; id[s1] = i; } 37 scanf("%d", &m); 38 double x; 39 while( m-- ) 40 { 41 cin >> s1; 42 scanf("%lf", &x); 43 cin >> s2; 44 int u = id[s1], v = id[s2]; 45 d[u][v] = x; 46 } 47 48 floyd(); 49 bool ok = false; 50 for(int i = 0; i < n; i++) if(d[i][i] > 1.0) { ok = true; break; } 51 printf("Case %d: %s\n", ++kase, ok ? "Yes" : "No"); 52 } 53 54 return 0; 55 }
1245 Saving James Bond 计算几何 最短路
这题用BFS过的,=_=
1 #include <cstdio> 2 #include <algorithm> 3 #include <cmath> 4 #include <queue> 5 using namespace std; 6 7 const int maxn = 100 + 10; 8 const double INF = 1e8; 9 const double eps = 1e-8; 10 11 inline int dcmp(double x) 12 { 13 if(fabs(x) < eps) return 0; 14 return x < 0 ? -1 : 1; 15 } 16 17 struct Point 18 { 19 double x, y; 20 Point(double x = 0, double y = 0):x(x), y(y) {} 21 }p[maxn]; 22 const Point O(0, 0); 23 24 Point operator - (const Point& A, const Point& B) 25 { return Point(A.x - B.x, A.y - B.y); } 26 27 double Dot(const Point& A, const Point& B) 28 { return A.x * B.x + A.y * B.y; } 29 30 double Length(const Point& A) { return sqrt(Dot(A, A)); } 31 32 double Dist(const Point& A, const Point& B) { return Length(A - B); } 33 34 int n; 35 double d; 36 double dis[maxn][maxn]; 37 38 void build_graph() 39 { 40 for(int i = 1; i <= n; i++) 41 { 42 dis[i][i] = 0; 43 for(int j = 1; j < i; j++) 44 dis[i][j] = dis[j][i] = Dist(p[i], p[j]); 45 } 46 for(int i = 1; i <= n; i++) 47 { 48 dis[0][i] = fabs(Dist(p[i], O) - 7.5); 49 dis[i][n + 1] = min(fabs(50.0 - fabs(p[i].x)), fabs(50.0 - fabs(p[i].y))); 50 dis[n + 1][i] = INF; 51 } 52 dis[0][n + 1] = INF; 53 } 54 55 double c[maxn]; 56 int step[maxn]; 57 58 void BFS() 59 { 60 for(int i = 1; i <= n + 1; i++) c[i] = INF; 61 c[0] = 0; 62 step[0] = 0; 63 queue<int> Q; 64 Q.push(0); 65 while(!Q.empty()) 66 { 67 int cur = Q.front(); Q.pop(); 68 for(int nxt = 1; nxt <= n + 1; nxt++) 69 { 70 if(dcmp(dis[cur][nxt] - d) <= 0) 71 { 72 int t = dcmp(c[nxt] - dis[cur][nxt] - c[cur]); 73 if(t > 0 || (t == 0 && step[nxt] > step[cur] + 1)) 74 { 75 c[nxt] = c[cur] + dis[cur][nxt]; 76 step[nxt] = step[cur] + 1; 77 Q.push(nxt); 78 } 79 } 80 } 81 } 82 } 83 84 int main() 85 { 86 while(scanf("%d%lf", &n, &d) == 2) 87 { 88 if(dcmp(d - 42.50) >= 0) { puts("42.50 %d"); continue; } 89 90 for(int i = 1; i <= n; i++) scanf("%lf%lf", &p[i].x, &p[i].y); 91 build_graph(); 92 BFS(); 93 if(dcmp(c[n + 1] - INF) == 0) puts("can't be saved"); 94 else printf("%.2f %d\n", c[n + 1], step[n + 1]); 95 } 96 97 return 0; 98 }
1317 XYZZY SPFA 判环
1 #include <cstdio> 2 #include <cstring> 3 #include <queue> 4 #include <vector> 5 using namespace std; 6 7 const int maxn = 100 + 10; 8 const int INF = 1000000000; 9 10 int n; 11 vector<int> G[maxn]; 12 int d[maxn], cnt[maxn], w[maxn]; 13 bool inq[maxn]; 14 15 bool SPFA() 16 { 17 memset(cnt, 0, sizeof(cnt)); 18 memset(inq, false, sizeof(inq)); 19 memset(d, 0, sizeof(d)); 20 queue<int> Q; 21 Q.push(1); 22 inq[1] = true; 23 d[1] = 100; 24 25 while(!Q.empty()) 26 { 27 int u = Q.front(); Q.pop(); 28 inq[u] = false; 29 cnt[u]++; 30 if(cnt[u] > n + 1) continue; 31 if(cnt[u] == n + 1) d[u] = INF; //有正环 32 for(int i = 0; i < G[u].size(); i++) 33 { 34 int v = G[u][i]; 35 if(d[v] < d[u] + w[v]) 36 { 37 if(v == n) return true; 38 d[v] = d[u] + w[v]; 39 if(!inq[v]) { inq[v] = true; Q.push(v); } 40 } 41 } 42 } 43 return false; 44 } 45 46 int main() 47 { 48 while(scanf("%d", &n) == 1 && n + 1) 49 { 50 for(int i = 1; i <= n; i++) G[i].clear(); 51 52 for(int i = 1; i <= n; i++) 53 { 54 int c; 55 scanf("%d%d", w + i, &c); 56 while(c--) 57 { 58 int u; scanf("%d", &u); 59 G[i].push_back(u); 60 } 61 } 62 63 printf("%s\n", SPFA() ? "winnable" : "hopeless"); 64 } 65 66 return 0; 67 }
1535 Invitation Cards 有向图的来回最短路,反向建图
1 #include <cstdio> 2 #include <cstring> 3 #include <vector> 4 #include <queue> 5 #include <map> 6 #define MP make_pair 7 using namespace std; 8 9 typedef pair<int, int> PII; 10 11 const int maxn = 1000000 + 10; 12 13 struct Edge 14 { 15 int from, to, dist; 16 Edge(int u, int v, int d):from(u), to(v), dist(d) {} 17 }; 18 19 int n, m; 20 21 vector<Edge> edges; 22 vector<int> G[maxn]; 23 int d[maxn], u[maxn], v[maxn], w[maxn]; 24 bool done[maxn]; 25 26 void init() 27 { 28 for(int i = 1; i <= n; i++) G[i].clear(); 29 edges.clear(); 30 } 31 32 void AddEdge(int from, int to, int dist) 33 { 34 edges.push_back(Edge(from, to, dist)); 35 int sz = edges.size(); 36 G[from].push_back(sz - 1); 37 } 38 39 void dijkstra() 40 { 41 memset(done, false, sizeof(done)); 42 memset(d, 0x3f, sizeof(d)); 43 d[1] = 0; 44 priority_queue<PII, vector<PII>, greater<PII> > Q; 45 Q.push(MP(0, 1)); 46 47 while(!Q.empty()) 48 { 49 PII x = Q.top(); Q.pop(); 50 int u = x.second; 51 if(done[u]) continue; 52 done[u] = true; 53 for(int i = 0; i < G[u].size(); i++) 54 { 55 Edge& e = edges[G[u][i]]; 56 if(d[e.to] > d[u] + e.dist) 57 { 58 d[e.to] = d[u] + e.dist; 59 Q.push(MP(d[e.to], e.to)); 60 } 61 } 62 } 63 } 64 65 int main() 66 { 67 int T; scanf("%d", &T); 68 while( T-- ) 69 { 70 scanf("%d%d", &n, &m); 71 for(int i = 0; i < m; i++) scanf("%d%d%d", u + i, v + i, w + i); 72 73 int ans = 0; 74 75 init(); 76 for(int i = 0; i < m; i++) AddEdge(u[i], v[i], w[i]); 77 dijkstra(); 78 for(int i = 2; i <= n; i++) ans += d[i]; 79 80 init(); 81 for(int i = 0; i < m; i++) AddEdge(v[i], u[i], w[i]); 82 dijkstra(); 83 for(int i = 2; i <= n; i++) ans += d[i]; 84 85 printf("%d\n", ans); 86 } 87 88 return 0; 89 }
1 #include <cstdio> 2 #include <cstring> 3 #include <vector> 4 #include <queue> 5 using namespace std; 6 7 const int maxn = 1000000 + 10; 8 9 int n, m; 10 int u[maxn], v[maxn], w[maxn]; 11 12 struct Edge 13 { 14 int from, to, dist; 15 Edge(int u, int v, int d):from(u), to(v), dist(d) {} 16 }; 17 18 vector<Edge> edges; 19 vector<int> G[maxn]; 20 21 void init() 22 { 23 for(int i = 1; i <= n; i++) G[i].clear(); 24 edges.clear(); 25 } 26 27 void AddEdge(int from, int to, int dist) 28 { 29 edges.push_back(Edge(from, to, dist)); 30 int sz = edges.size(); 31 G[from].push_back(sz - 1); 32 } 33 34 bool inq[maxn]; 35 int d[maxn]; 36 37 void SPFA() 38 { 39 queue<int> Q; 40 memset(inq, false, sizeof(inq)); 41 memset(d, 0x3f, sizeof(d)); 42 inq[1] = true; 43 Q.push(1); 44 d[1] = 0; 45 46 while(!Q.empty()) 47 { 48 int u = Q.front(); Q.pop(); 49 inq[u] = false; 50 for(int i = 0; i < G[u].size(); i++) 51 { 52 Edge& e = edges[G[u][i]]; 53 if(d[e.to] > d[u] + e.dist) 54 { 55 d[e.to] = d[u] + e.dist; 56 if(!inq[e.to]) { inq[e.to] = true; Q.push(e.to); } 57 } 58 } 59 } 60 } 61 62 int main() 63 { 64 int T; scanf("%d", &T); 65 while(T--) 66 { 67 scanf("%d%d", &n, &m); 68 for(int i = 0; i < m; i++) scanf("%d%d%d", u + i, v + i, w + i); 69 70 int ans = 0; 71 72 init(); 73 for(int i = 0; i < m; i++) AddEdge(u[i], v[i], w[i]); 74 SPFA(); 75 for(int i = 2; i <= n; i++) ans += d[i]; 76 77 init(); 78 for(int i = 0; i < m; i++) AddEdge(v[i], u[i], w[i]); 79 SPFA(); 80 for(int i = 2; i <= n; i++) ans += d[i]; 81 82 printf("%d\n", ans); 83 } 84 85 return 0; 86 }
1546 Idiomatic Phrases Game 成语接龙,最短路
1 #include <cstdio> 2 #include <cstring> 3 #include <queue> 4 #include <algorithm> 5 using namespace std; 6 7 const int maxn = 1000 + 10; 8 const int INF = 0x3f3f3f3f; 9 const int maxl = 200; 10 11 int n; 12 13 char dic[maxn][maxl]; 14 int w[maxn]; 15 int dis[maxn][maxn]; 16 int d[maxn]; 17 bool done[maxn]; 18 19 inline bool connect(int a, int b) 20 { 21 int l = strlen(dic[a]); 22 for(int i = 0; i < 4; i++) if(dic[a][l-4+i] != dic[b][i]) return false; 23 return true; 24 } 25 26 void dijkstra() 27 { 28 memset(d, 0x3f, sizeof(d)); 29 d[0] = 0; 30 memset(done, false, sizeof(done)); 31 for(int i = 0; i < n; i++) 32 { 33 int x, m = INF; 34 for(int y = 0; y < n; y++) if(d[y] <= m && !done[y]) m = d[x = y]; 35 done[x] = true; 36 for(int y = 0; y < n; y++) d[y] = min(d[y], d[x] + dis[x][y]); 37 } 38 } 39 40 int main() 41 { 42 //freopen("in.txt", "r", stdin); 43 44 while(scanf("%d", &n) == 1 && n) 45 { 46 for(int i = 0; i < n; i++) scanf("%d %s", w + i, dic[i]); 47 48 if(n == 1) { puts("-1"); continue; } 49 50 //build_graph 51 for(int i = 0; i < n; i++) 52 { 53 for(int j = 0; j < n; j++) 54 { 55 if(i == j) { dis[i][j] = INF; continue; } 56 if(connect(i, j)) dis[i][j] = w[i]; 57 else dis[i][j] = INF; 58 } 59 } 60 61 dijkstra(); 62 printf("%d\n", d[n - 1] == INF ? -1 : d[n - 1]); 63 } 64 65 return 0; 66 }
1 #include <cstdio> 2 #include <cstring> 3 #include <queue> 4 using namespace std; 5 6 const int maxn = 1000 + 10; 7 const int maxl = 200; 8 const int INF = 0x3f3f3f3f; 9 10 int n; 11 int d[maxn], w[maxn]; 12 vector<int> G[maxn]; 13 bool inq[maxn]; 14 char dic[maxn][maxl]; 15 16 inline bool connect(int a, int b) 17 { 18 int l = strlen(dic[a]); 19 for(int i = 0; i < 4; i++) if(dic[a][l-4+i] != dic[b][i]) return false; 20 return true; 21 } 22 23 void SPFA() 24 { 25 memset(inq, false, sizeof(inq)); 26 memset(d, 0x3f, sizeof(d)); 27 queue<int> Q; 28 Q.push(0); 29 inq[0] = true; 30 d[0] = 0; 31 32 while(!Q.empty()) 33 { 34 int u = Q.front(); Q.pop(); 35 inq[u] = false; 36 for(int i = 0; i < G[u].size(); i++) 37 { 38 int v = G[u][i]; 39 if(d[v] > d[u] + w[u]) 40 { 41 d[v] = d[u] + w[u]; 42 if(!inq[v]) { inq[v] = true; Q.push(v); } 43 } 44 } 45 } 46 } 47 48 int main() 49 { 50 //freopen("in.txt", "r", stdin); 51 52 while(scanf("%d", &n) == 1 && n) 53 { 54 for(int i = 0; i < n; i++) scanf("%d %s", w + i, dic[i]); 55 56 if(n == 1) { puts("-1"); continue; } 57 58 //build_graph 59 for(int i = 0; i < n; i++) G[i].clear(); 60 for(int i = 0; i < n; i++) 61 { 62 for(int j = 0; j < n; j++) 63 { 64 if(i == j) continue; 65 if(connect(i, j)) G[i].push_back(j); 66 } 67 } 68 69 SPFA(); 70 printf("%d\n", d[n - 1] == INF ? -1 : d[n - 1]); 71 } 72 73 return 0; 74 }
2680 Choose the best route 最短路,多个源点
1 #include <cstdio> 2 #include <cstring> 3 #include <vector> 4 #include <queue> 5 #include <map> 6 #define MP make_pair 7 using namespace std; 8 typedef pair<int, int> PII; 9 10 const int maxn = 1000 + 10; 11 const int INF = 0x3f3f3f3f; 12 13 int n, m, s[maxn], t, c; 14 15 struct Edge 16 { 17 int from, to, dist; 18 Edge(int u, int v, int d):from(u), to(v), dist(d) {} 19 }; 20 21 vector<Edge> edges; 22 vector<int> G[maxn]; 23 24 void init() 25 { 26 for(int i = 1; i <= n; i++) G[i].clear(); 27 edges.clear(); 28 } 29 30 void AddEdge(int from, int to, int dist) 31 { 32 edges.push_back(Edge(from, to, dist)); 33 int sz = edges.size(); 34 G[from].push_back(sz - 1); 35 } 36 37 int d[maxn]; 38 bool done[maxn]; 39 40 void dijkstra() 41 { 42 memset(done, false, sizeof(done)); 43 memset(d, 0x3f, sizeof(d)); 44 priority_queue<PII, vector<PII>, greater<PII> > Q; 45 for(int i = 0; i < c; i++) 46 { 47 d[s[i]] = 0; 48 Q.push(MP(0, s[i])); 49 } 50 51 while(!Q.empty()) 52 { 53 PII x = Q.top(); Q.pop(); 54 int u = x.second; 55 if(done[u]) continue; 56 done[u] = true; 57 for(int i = 0; i < G[u].size(); i++) 58 { 59 Edge& e = edges[G[u][i]]; 60 int v = e.to; 61 if(d[v] > d[u] + e.dist) 62 { 63 d[v] = d[u] + e.dist; 64 Q.push(MP(d[v], v)); 65 } 66 } 67 } 68 } 69 70 int main() 71 { 72 while(scanf("%d%d%d", &n, &m, &t) == 3) 73 { 74 init(); 75 for(int i = 0; i < m; i++) 76 { 77 int u, v, w; 78 scanf("%d%d%d", &u, &v, &w); 79 AddEdge(u, v, w); 80 } 81 scanf("%d", &c); 82 for(int i = 0; i < c; i++) scanf("%d", s + i); 83 dijkstra(); 84 printf("%d\n", d[t] == INF ? -1 : d[t]); 85 } 86 87 return 0; 88 }
1 #include <cstdio> 2 #include <cstring> 3 #include <queue> 4 #include <vector> 5 using namespace std; 6 7 const int maxn = 1000 + 10; 8 const int INF = 0x3f3f3f3f; 9 10 int n, m, s[maxn], t, c; 11 12 struct Edge 13 { 14 int from, to, dist; 15 Edge(int u, int v, int d):from(u), to(v), dist(d) {} 16 }; 17 18 vector<Edge> edges; 19 vector<int> G[maxn]; 20 21 void init() 22 { 23 for(int i = 1; i <= n; i++) G[i].clear(); 24 edges.clear(); 25 } 26 27 void AddEdge(int from, int to, int dist) 28 { 29 edges.push_back(Edge(from, to, dist)); 30 int sz = edges.size(); 31 G[from].push_back(sz - 1); 32 } 33 34 int d[maxn]; 35 bool inq[maxn]; 36 37 void SPFA() 38 { 39 memset(inq, false, sizeof(inq)); 40 memset(d, 0x3f, sizeof(d)); 41 queue<int> Q; 42 for(int i = 0; i < c; i++) 43 { 44 d[s[i]] = 0; 45 inq[s[i]] = true; 46 Q.push(s[i]); 47 } 48 49 while(!Q.empty()) 50 { 51 int u = Q.front(); Q.pop(); 52 inq[u] = false; 53 for(int i = 0; i < G[u].size(); i++) 54 { 55 Edge& e = edges[G[u][i]]; 56 int v = e.to; 57 if(d[v] > d[u] + e.dist) 58 { 59 d[v] = d[u] + e.dist; 60 if(!inq[v]) { inq[v] = true; Q.push(v); } 61 } 62 } 63 } 64 } 65 66 int main() 67 { 68 while(scanf("%d%d%d", &n, &m, &t) == 3) 69 { 70 init(); 71 int u, v, w; 72 while( m-- ) { scanf("%d%d%d", &u, &v, &w); AddEdge(u, v, w); } 73 scanf("%d", &c); 74 for(int i = 0; i < c; i++) scanf("%d", s + i); 75 SPFA(); 76 printf("%d\n", d[t] == INF ? -1 : d[t]); 77 } 78 79 return 0; 80 }
2923 Einbahnstrasse 最短路,Floyd,注意处理好输入格式
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <string> 5 #include <map> 6 #include <algorithm> 7 using namespace std; 8 9 const int maxn = 100 + 10; 10 11 int n, C, m; 12 int s, cnt[maxn]; 13 int tot; 14 int d[maxn][maxn]; 15 16 map<string, int> id; 17 18 void init() 19 { 20 tot = 0; 21 id.clear(); 22 memset(d, 0x3f, sizeof(d)); 23 memset(cnt, 0, sizeof(cnt)); 24 } 25 26 int ID(string s) 27 { 28 if(!id.count(s)) id[s] = tot++; 29 return id[s]; 30 } 31 32 void floyd() 33 { 34 for(int k = 0; k < n; k++) 35 for(int i = 0; i < n; i++) 36 for(int j = 0; j < n; j++) 37 d[i][j] = min(d[i][j], d[i][k] + d[k][j]); 38 } 39 40 int main() 41 { 42 int kase = 0; 43 44 while(scanf("%d%d%d", &n, &C, &m) == 3) 45 { 46 if(!n && !C && !m) break; 47 init(); 48 string s1, s2, s3; 49 cin >> s1; s = ID(s1); 50 for(int i = 0; i < C; i++) { cin >> s1; cnt[ID(s1)]++; } 51 52 for(int i = 0; i < m; i++) 53 { 54 cin >> s1 >> s2 >> s3; 55 int u = ID(s1), v = ID(s3); 56 int l = s2.length(); 57 int t = 0; 58 for(int j = 2; j < l - 2; j++) t = t * 10 + (s2[j] - '0'); 59 if(s2[0] == '<') d[v][u] = min(d[v][u], t); 60 if(s2[l-1] == '>') d[u][v] = min(d[u][v], t); 61 } 62 63 floyd(); 64 65 int ans = 0; 66 for(int i = 0; i < n; i++) if(cnt[i]) 67 ans += cnt[i] * (d[0][i] + d[i][0]); 68 69 printf("%d. %d\n", ++kase, ans); 70 } 71 72 return 0; 73 }
3339 In Action 最短路 + 01背包
用最短的路径,摧毁多于一半的电力。
把每个点的最短路径看做体积,每个点的电力看做价值。
求多于总价值一半的最小背包容量。
1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 #include <queue> 5 #include <vector> 6 using namespace std; 7 8 const int maxn = 100 + 10; 9 const int INF = 0x3f3f3f3f; 10 11 int n, m; 12 int w[maxn]; 13 14 struct Edge 15 { 16 int from, to, dist; 17 Edge(int u, int v, int d):from(u), to(v), dist(d) {} 18 }; 19 20 vector<Edge> edges; 21 vector<int> G[maxn]; 22 int d[maxn]; 23 bool inq[maxn]; 24 25 void init() 26 { 27 for(int i = 0; i <= n; i++) G[i].clear(); 28 edges.clear(); 29 memset(d, 0x3f, sizeof(d)); 30 } 31 32 void AddEdge(int u, int v, int d) 33 { 34 edges.push_back(Edge(u, v, d)); 35 int sz = edges.size(); 36 G[u].push_back(sz - 1); 37 } 38 39 void SPFA() 40 { 41 memset(inq, false, sizeof(inq)); 42 inq[0] = true; 43 queue<int> Q; 44 Q.push(0); 45 d[0] = 0; 46 47 while(!Q.empty()) 48 { 49 int u = Q.front(); Q.pop(); 50 inq[u] = false; 51 for(int i = 0; i < G[u].size(); i++) 52 { 53 Edge& e = edges[G[u][i]]; 54 int v = e.to; 55 if(d[v] > d[u] + e.dist) 56 { 57 d[v] = d[u] + e.dist; 58 if(!inq[v]) { inq[v] = true; Q.push(v); } 59 } 60 } 61 } 62 } 63 64 const int maxc = 100000; 65 int f[maxc]; 66 67 int main() 68 { 69 int T; scanf("%d", &T); 70 while( T-- ) 71 { 72 init(); 73 74 scanf("%d%d", &n, &m); 75 while(m--) 76 { 77 int u, v, d; 78 scanf("%d%d%d", &u, &v, &d); 79 AddEdge(u, v, d); 80 AddEdge(v, u, d); 81 } 82 SPFA(); 83 84 int sumv = 0; 85 for(int i = 1; i <= n; i++) { scanf("%d", w + i); sumv += w[i]; } 86 sumv = (sumv >> 1) + 1; 87 88 int sumc = 0, temp = 0; 89 for(int i = 1; i <= n; i++) if(d[i] < INF) { sumc += d[i]; temp += w[i]; } 90 if(temp < sumv) { puts("impossible"); continue; } 91 92 //ZeroOnePack 93 memset(f, 0, sizeof(f)); 94 for(int i = 1; i <= n; i++) if(d[i] < INF) 95 { 96 for(int j = sumc; j >= d[i]; j--) 97 f[j] = max(f[j], f[j - d[i]] + w[i]); 98 } 99 int ans = lower_bound(f, f + sumc, sumv) - f; 100 printf("%d\n", ans); 101 } 102 103 return 0; 104 }
2224 The shortest path 双调旅行商问题
这其实是一道DP,紫书上动态规划那章有这个原题。
1 #include <cstdio> 2 #include <cstring> 3 #include <cmath> 4 #include <algorithm> 5 using namespace std; 6 7 struct Point 8 { 9 double x, y; 10 Point(double x = 0, double y = 0):x(x), y(y) {} 11 bool operator < (const Point& rhs) const { return x < rhs.x; } 12 }; 13 14 const int maxn = 200 + 10; 15 16 int n; 17 double dis[maxn][maxn], d[maxn][maxn]; 18 Point p[maxn]; 19 20 inline double Dist(int i, int j) 21 { 22 double dx = p[i].x - p[j].x; 23 double dy = p[i].y - p[j].y; 24 return sqrt(dx * dx + dy * dy); 25 } 26 27 int main() 28 { 29 while(scanf("%d", &n) == 1) 30 { 31 for(int i = 1; i <= n; i++) scanf("%lf%lf", &p[i].x, &p[i].y); 32 for(int i = 1; i <= n; i++) 33 { 34 dis[i][i] = 0; 35 for(int j = i + 1; j <= n; j++) 36 dis[i][j] = dis[j][i] = Dist(i, j); 37 } 38 39 memset(d, 0, sizeof(d)); 40 d[2][1] = dis[2][1]; 41 for(int i = n - 1; i > 1; i--) 42 for(int j = 1; j < i; j++) 43 { 44 if(i == n - 1) d[i][j] = dis[i][n] + dis[j][n]; 45 else d[i][j] = min(d[i+1][j] + dis[i][i+1], d[i+1][i] + dis[j][i+1]); 46 } 47 48 printf("%.2f\n", d[2][1] + dis[2][1]); 49 } 50 51 return 0; 52 }
2807 The Shortest Path 矩阵运算 Floyd最短路
好像没什么难点,直接暴力过的,注意里面都是有向边
1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 using namespace std; 5 6 const int maxn = 100; 7 const int INF = 0x3f3f3f3f; 8 9 typedef int Matrix[maxn][maxn]; 10 11 int n, m; 12 Matrix M[maxn]; 13 int d[maxn][maxn]; 14 15 void floyd() 16 { 17 for(int k = 0; k < n; k++) 18 for(int i = 0; i < n; i++) 19 for(int j = 0; j < n; j++) 20 d[i][j] = min(d[i][j], d[i][k] + d[k][j]); 21 } 22 23 int main() 24 { 25 while(scanf("%d%d", &n, &m) == 2) 26 { 27 if(n == 0 && m == 0) break; 28 29 memset(d, 0x3f, sizeof(d)); 30 31 for(int i = 0; i < n; i++) 32 { 33 for(int j = 0; j < m; j++) 34 for(int k = 0; k < m; k++) 35 scanf("%d", &M[i][j][k]); 36 } 37 38 for(int i = 0; i < n; i++) 39 { 40 for(int j = 0; j < n; j++) if(i != j) 41 { 42 //Matrix Multiplication 43 Matrix temp; 44 memset(temp, 0, sizeof(temp)); 45 for(int ii = 0; ii < m; ii++) 46 for(int jj = 0; jj < m; jj++) 47 for(int kk = 0; kk < m; kk++) 48 temp[ii][jj] += M[i][ii][kk] * M[j][kk][jj]; 49 50 for(int k = 0; k < n; k++) if(i != k && j != k) 51 { 52 bool eq = true; 53 for(int r = 0; r < m && eq; r++) 54 for(int c = 0; c < m; c++) 55 if(temp[r][c] != M[k][r][c]) { eq = false; break; } 56 57 //Matrix i * j equals k 58 if(eq) d[i][k] = 1; 59 } 60 } 61 } 62 63 floyd(); 64 65 int Q; scanf("%d", &Q); 66 while(Q--) 67 { 68 int u, v; 69 scanf("%d%d", &u, &v); 70 u--; v--; 71 if(d[u][v] == INF) puts("Sorry"); 72 else printf("%d\n", d[u][v]); 73 } 74 } 75 76 return 0; 77 }
1595 find the longest of the shortest 删掉任意一条边的最长最短路
先求一遍最短路,然后枚举最短路径上的边,将其删掉再求最短路。
因为删掉其他边的话,是不影响到终点的最短距离的。
Dijkstra 436MS
1 /* 2 Dijkstra 436MS 3 */ 4 #include <cstdio> 5 #include <cstring> 6 #include <queue> 7 #include <vector> 8 #define MP make_pair 9 using namespace std; 10 typedef pair<int, int> PII; 11 12 const int maxn = 1000 + 10; 13 const int INF = 0x3f3f3f3f; 14 15 struct Edge 16 { 17 int from, to, dist; 18 Edge(int u, int v, int d):from(u), to(v), dist(d) {} 19 }; 20 21 int n, m; 22 23 vector<Edge> edges; 24 vector<int> G[maxn]; 25 vector<int> id; 26 int d[maxn], p[maxn]; 27 bool done[maxn]; 28 29 void init() 30 { 31 for(int i = 1; i <= n; i++) G[i].clear(); 32 edges.clear(); 33 id.clear(); 34 } 35 36 void AddEdge(int u, int v, int d) 37 { 38 edges.push_back(Edge(u, v, d)); 39 edges.push_back(Edge(v, u, d)); 40 int sz = edges.size(); 41 G[u].push_back(sz - 2); 42 G[v].push_back(sz - 1); 43 } 44 45 int dijkstra(int no) 46 { 47 priority_queue<PII, vector<PII>, greater<PII> > Q; 48 memset(d, 0x3f, sizeof(d)); 49 d[1] = 0; 50 memset(done, false, sizeof(done)); 51 Q.push(MP(0, 1)); 52 if(no == -1) memset(p, 0, sizeof(p)); 53 54 while(!Q.empty()) 55 { 56 PII x = Q.top(); Q.pop(); 57 int u = x.second; 58 if(done[u]) continue; 59 done[u] = true; 60 for(int i = 0; i < G[u].size(); i++) 61 { 62 int id = G[u][i]; 63 if(id == no || id == (no ^ 1)) continue; //This edge is deleted 64 Edge& e = edges[id]; 65 int v = e.to; 66 if(d[v] > d[u] + e.dist) 67 { 68 d[v] = d[u] + e.dist; 69 if(no < 0) p[v] = id; 70 Q.push(MP(d[v], v)); 71 } 72 } 73 } 74 return d[n]; 75 } 76 77 int main() 78 { 79 while(scanf("%d%d", &n, &m) == 2) 80 { 81 init(); 82 83 for(int i = 0; i < m; i++) 84 { 85 int u, v, d; scanf("%d%d%d", &u, &v, &d); 86 AddEdge(u, v, d); 87 } 88 89 dijkstra(-1); 90 int id = p[n], ans = 0; 91 while(id) { ans = max(ans, dijkstra(id)); id = p[edges[id].from]; } 92 93 printf("%d\n", ans); 94 } 95 96 return 0; 97 }
SPFA 826MS
1 /* 2 SPFA 826MS 3 */ 4 #include <cstdio> 5 #include <cstring> 6 #include <algorithm> 7 #include <queue> 8 #include <vector> 9 using namespace std; 10 11 const int maxn = 1000 + 10; 12 13 struct Edge 14 { 15 int from, to, dist; 16 Edge(int u, int v, int d):from(u), to(v), dist(d) {} 17 }; 18 19 int n, m; 20 21 vector<Edge> edges; 22 vector<int> G[maxn]; 23 int d[maxn], p[maxn]; 24 bool inq[maxn]; 25 26 void init() 27 { 28 for(int i = 1; i <= n; i++) G[i].clear(); 29 edges.clear(); 30 } 31 32 void AddEdge(int u, int v, int d) 33 { 34 edges.push_back(Edge(u, v, d)); 35 edges.push_back(Edge(v, u, d)); 36 int sz = edges.size(); 37 G[u].push_back(sz - 2); 38 G[v].push_back(sz - 1); 39 } 40 41 int SPFA(int no) 42 { 43 memset(inq, false, sizeof(inq)); 44 inq[1] = true; 45 queue<int> Q; 46 Q.push(1); 47 memset(d, 0x3f, sizeof(d)); 48 d[1] = 0; 49 if(no < 0) memset(p, 0, sizeof(p)); 50 51 while(!Q.empty()) 52 { 53 int u = Q.front(); Q.pop(); 54 inq[u] = false; 55 for(int i = 0; i < G[u].size(); i++) 56 { 57 int id = G[u][i]; 58 if(id == no || id == (no ^ 1)) continue; 59 Edge& e = edges[id]; 60 int v = e.to; 61 if(d[v] > d[u] + e.dist) 62 { 63 d[v] = d[u] + e.dist; 64 if(no < 0) p[v] = id; 65 if(!inq[v]) { inq[v] = true; Q.push(v); } 66 } 67 } 68 } 69 70 return d[n]; 71 } 72 73 int main() 74 { 75 while(scanf("%d%d", &n, &m) == 2) 76 { 77 init(); 78 79 //build graph 80 while( m-- ) 81 { 82 int u, v, d; 83 scanf("%d%d%d", &u, &v, &d); 84 AddEdge(u, v, d); 85 } 86 87 SPFA(-1); 88 89 int ans = 0, id = p[n]; 90 while(id) { ans = max(ans, SPFA(id)); id = p[edges[id].from]; } 91 92 printf("%d\n", ans); 93 } 94 95 return 0; 96 }
3986 Harry Potter and the Final Battle 同上题
一旦出现到达不了的情况就及时输出。
Dijkstra 374MS
1 /* 2 Dijkstra 374MS 3 莫名其妙地改了一下第93行代码就AC了 4 */ 5 6 #include <cstdio> 7 #include <cstring> 8 #include <queue> 9 #include <vector> 10 #define MP make_pair 11 using namespace std; 12 typedef pair<int, int> PII; 13 14 const int maxn = 1000 + 10; 15 const int INF = 0x3f3f3f3f; 16 17 struct Edge 18 { 19 int from, to, dist; 20 Edge(int u, int v, int d):from(u), to(v), dist(d) {} 21 }; 22 23 int n, m; 24 25 vector<Edge> edges; 26 vector<int> G[maxn]; 27 int d[maxn], p[maxn]; 28 bool done[maxn]; 29 30 void init() 31 { 32 for(int i = 1; i <= n; i++) G[i].clear(); 33 edges.clear(); 34 } 35 36 void AddEdge(int u, int v, int d) 37 { 38 edges.push_back(Edge(u, v, d)); 39 edges.push_back(Edge(v, u, d)); 40 int sz = edges.size(); 41 G[u].push_back(sz - 2); 42 G[v].push_back(sz - 1); 43 } 44 45 int dijkstra(int no) 46 { 47 priority_queue<PII, vector<PII>, greater<PII> > Q; 48 memset(d, 0x3f, sizeof(d)); 49 d[1] = 0; 50 memset(done, false, sizeof(done)); 51 Q.push(MP(0, 1)); 52 if(no == -1) memset(p, -1, sizeof(p)); 53 54 while(!Q.empty()) 55 { 56 PII x = Q.top(); Q.pop(); 57 int u = x.second; 58 if(done[u]) continue; 59 done[u] = true; 60 for(int i = 0; i < G[u].size(); i++) 61 { 62 int id = G[u][i]; 63 if(id == no || id == (no ^ 1)) continue; 64 Edge& e = edges[id]; 65 int v = e.to; 66 if(d[v] > d[u] + e.dist) 67 { 68 d[v] = d[u] + e.dist; 69 if(no < 0) p[v] = id; 70 Q.push(MP(d[v], v)); 71 } 72 } 73 } 74 return d[n]; 75 } 76 77 int main() 78 { 79 int T; scanf("%d", &T); 80 while(T--) 81 { 82 scanf("%d%d", &n, &m); 83 init(); 84 85 for(int i = 0; i < m; i++) 86 { 87 int u, v, d; scanf("%d%d%d", &u, &v, &d); 88 AddEdge(u, v, d); 89 } 90 91 int ans = dijkstra(-1); 92 int id = p[n]; 93 while(ans < INF && id != -1) { ans = max(ans, dijkstra(id)); id = p[edges[id].from]; } 94 95 printf("%d\n", ans == INF ? -1 : ans); 96 } 97 98 return 0; 99 }
SPFA 234MS
1 /* 2 SPFA 234MS 3 */ 4 #include <cstdio> 5 #include <cstring> 6 #include <queue> 7 #include <vector> 8 #include <algorithm> 9 using namespace std; 10 11 struct Edge 12 { 13 int from, to, dist; 14 Edge(int u, int v, int d):from(u), to(v), dist(d) {} 15 }; 16 17 const int maxn = 1000 + 10; 18 const int INF = 0x3f3f3f3f; 19 20 int n, m; 21 22 vector<Edge> edges; 23 vector<int> G[maxn]; 24 int d[maxn], p[maxn]; 25 bool inq[maxn]; 26 27 void init() 28 { 29 for(int i = 1; i <= n; i++) G[i].clear(); 30 edges.clear(); 31 } 32 33 void AddEdge(int u, int v, int d) 34 { 35 edges.push_back(Edge(u, v, d)); 36 edges.push_back(Edge(v, u, d)); 37 int sz = edges.size(); 38 G[u].push_back(sz - 2); 39 G[v].push_back(sz - 1); 40 } 41 42 int SPFA(int no) 43 { 44 memset(inq, false, sizeof(inq)); 45 inq[1] = true; 46 queue<int> Q; 47 Q.push(1); 48 memset(d, 0x3f, sizeof(d)); 49 d[1] = 0; 50 if(no < 0) memset(p, -1, sizeof(p)); 51 52 while(!Q.empty()) 53 { 54 int u = Q.front(); Q.pop(); 55 inq[u] = false; 56 for(int i = 0; i < G[u].size(); i++) 57 { 58 int id = G[u][i]; 59 if(id == no || id == (no ^ 1)) continue; 60 Edge& e = edges[id]; 61 int v = e.to; 62 if(d[v] > d[u] + e.dist) 63 { 64 d[v] = d[u] + e.dist; 65 if(no < 0) p[v] = id; 66 if(!inq[v]) { inq[v] = true; Q.push(v); } 67 } 68 } 69 } 70 return d[n]; 71 } 72 73 int main() 74 { 75 int T; scanf("%d", &T); 76 while( T-- ) 77 { 78 scanf("%d%d", &n, &m); 79 init(); 80 81 //build graph 82 while( m-- ) 83 { 84 int u, v, d; 85 scanf("%d%d%d", &u, &v, &d); 86 AddEdge(u, v, d); 87 } 88 89 int ans = SPFA(-1); 90 int id = p[n]; 91 while(ans < INF && id != -1) { ans = max(ans, SPFA(id)); id = p[edges[id].from]; } 92 93 printf("%d\n", ans == INF ? -1 : ans); 94 } 95 96 return 0; 97 }
1599 find the mincost route Floyd变体,求最小环
1 #include <cstdio> 2 #include <algorithm> 3 using namespace std; 4 5 const int INF = 100000000; 6 const int maxn = 100 + 10; 7 8 int n, m; 9 int d[maxn][maxn], dis[maxn][maxn]; 10 11 void floyd() 12 { 13 for(int i = 1; i <= n; i++) 14 for(int j = 1; j <= n; j++) 15 d[i][j] = dis[i][j]; 16 int ans = INF; 17 for(int k = 1; k <= n; k++) 18 { 19 for(int i = 1; i < k; i++) 20 for(int j = i + 1; j < k; j++) 21 ans = min(ans, d[i][j] + dis[i][k] + dis[k][j]);//INF太大的话这里会溢出!! 22 23 for(int i = 1; i <= n; i++) 24 for(int j = 1; j <= n; j++) 25 d[i][j] = min(d[i][j], d[i][k] + d[k][j]); 26 } 27 if(ans == INF) puts("It's impossible."); 28 else printf("%d\n", ans); 29 } 30 31 int main() 32 { 33 while(scanf("%d%d", &n, &m) == 2) 34 { 35 for(int i = 1; i <= n; i++) 36 for(int j = 1; j <= n; j++) dis[i][j] = INF; 37 while( m-- ) 38 { 39 int u, v, dist; 40 scanf("%d%d%d", &u, &v, &dist); 41 if(dist < dis[u][v]) dis[u][v] = dis[v][u] = dist; 42 } 43 floyd(); 44 } 45 46 return 0; 47 }
1839 Delay Constrained... 二分最小流量 + 最短路(带限制最短路)
1 #include <cstdio> 2 #include <vector> 3 #include <cstring> 4 #include <algorithm> 5 #include <map> 6 #include <queue> 7 #define MP make_pair 8 using namespace std; 9 typedef pair<int, int> PII; 10 11 const int maxn = 10000 + 10; 12 const int INF = 0x3f3f3f3f; 13 14 struct Edge 15 { 16 int from, to, cap, dist; 17 Edge(int u, int v, int c, int d):from(u), to(v), cap(c), dist(d) {} 18 }; 19 20 int n, m, T; 21 22 vector<Edge> edges; 23 vector<int> G[maxn]; 24 int d[maxn], p[maxn]; 25 bool done[maxn]; 26 27 void init() 28 { 29 for(int i = 1; i <= n; i++) G[i].clear(); 30 edges.clear(); 31 } 32 33 void AddEdge(int u, int v, int c, int d) 34 { 35 edges.push_back(Edge(u, v, c, d)); 36 edges.push_back(Edge(v, u, c, d)); 37 int sz = edges.size(); 38 G[u].push_back(sz - 2); 39 G[v].push_back(sz - 1); 40 } 41 42 bool dijkstra(int C, int& temp) 43 { 44 memset(p, -1, sizeof(p)); 45 memset(d, 0x3f, sizeof(d)); 46 d[1] = 0; 47 priority_queue<PII, vector<PII>, greater<PII> > Q; 48 Q.push(MP(0, 1)); 49 50 while(!Q.empty()) 51 { 52 PII x = Q.top(); Q.pop(); 53 int u = x.second; 54 for(int i = 0; i < G[u].size(); i++) 55 { 56 Edge& e = edges[G[u][i]]; 57 int v = e.to; 58 if(e.cap < C) continue; 59 if(d[v] > d[u] + e.dist) 60 { 61 d[v] = d[u] + e.dist; 62 p[v] = G[u][i]; 63 Q.push(MP(d[v], v)); 64 } 65 } 66 } 67 68 temp = INF; 69 int id = p[n]; 70 while(id != -1) { temp = min(temp, edges[id].cap); id = p[edges[id].from]; } 71 72 return d[n] <= T; 73 } 74 75 int main() 76 { 77 //freopen("in.txt", "r", stdin); 78 79 int test; scanf("%d", &test); 80 while( test-- ) 81 { 82 init(); 83 scanf("%d%d%d", &n, &m, &T); 84 int maxc = 0; 85 while(m--) 86 { 87 int u, v, c, d; 88 scanf("%d%d%d%d", &u, &v, &c, &d); 89 maxc = max(maxc, c); 90 AddEdge(u, v, c, d); 91 } 92 93 int L = 0, R = maxc; 94 int temp; 95 while(L < R) 96 { 97 int mid = (L + R) / 2 + 1; 98 if(dijkstra(mid, temp)) L = temp; 99 else R = mid - 1; 100 } 101 printf("%d\n", L); 102 } 103 104 return 0; 105 }
3631 Shortest Path Floyd插点法
每次新加进来一个点,将其作为中间点作一轮松弛操作
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 #include <vector> 6 using namespace std; 7 8 const int maxn = 300 + 10; 9 const int INF = 0x3f3f3f3f; 10 11 int n, m, Q; 12 int d[maxn][maxn]; 13 bool marked[maxn]; 14 15 void init() 16 { 17 memset(marked, false, sizeof(marked)); 18 memset(d, 0x3f, sizeof(d)); 19 for(int i = 0; i < n; i++) d[i][i] = 0; 20 } 21 22 int main() 23 { 24 int kase = 0; 25 while(scanf("%d%d%d", &n, &m, &Q) == 3) 26 { 27 if(n == 0 && m == 0 && Q == 0) break; 28 29 if(kase) puts(""); 30 printf("Case %d:\n", ++kase); 31 32 init(); 33 int op, u, v; 34 for(int i = 0; i < m; i++) 35 { 36 int dist; 37 scanf("%d%d%d", &u, &v, &dist); 38 if(d[u][v] > dist) d[u][v] = dist; 39 } 40 41 while(Q--) 42 { 43 scanf("%d%d", &op, &u); 44 45 if(op == 0) 46 { 47 if(marked[u]) { printf("ERROR! At point %d\n", u); continue; } 48 marked[u] = true; 49 50 for(int i = 0; i < n; i++) 51 for(int j = 0; j < n; j++) 52 d[i][j] = min(d[i][j], d[i][u] + d[u][j]); 53 } 54 else 55 { 56 scanf("%d", &v); 57 if(!marked[u] || !marked[v]) { printf("ERROR! At path %d to %d\n", u, v); continue; } 58 if(d[u][v] == INF) { puts("No such path"); continue; } 59 printf("%d\n", d[u][v]); 60 } 61 } 62 } 63 64 return 0; 65 }
4114 Disney's FastPass 最短路 + 状压DP
Floyd预处理一遍两点之间的最短路
state[S1][S2][u]表示已参观过的景点为S1,已有的门票为S2,当前位置为u的最短时间
1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 using namespace std; 5 6 const int maxn = 55; 7 const int INF = 0x3f3f3f3f; 8 const int maxS = (1 << 8) + 10; 9 10 int n, m, k; 11 int ans; 12 int d[maxn][maxn]; 13 int p[maxn], t[maxn], ft[maxn]; 14 int state[maxn]; //state[S1][S2][u]表示已参观过的景点为S1,已有的门票为S2,当前位置为u 15 16 void init() 17 { 18 memset(d, 0x3f, sizeof(d)); 19 for(int i = 0; i < n; i++) d[i][i] = 0; 20 memset(state, 0, sizeof(state)); 21 } 22 23 void floyd() 24 { 25 for(int k = 0; k < n; k++) 26 for(int i = 0; i < n; i++) 27 for(int j = 0; j < n; j++) 28 d[i][j] = min(d[i][j], d[i][k] + d[k][j]); 29 } 30 31 int dp[maxS][maxS][maxn]; 32 33 void DP() 34 { 35 memset(dp, 0x3f, sizeof(dp)); 36 dp[0][0][0] = 0; 37 38 int tot = (1 << k) - 1; 39 for(int S1 = 0; S1 <= tot; S1++) 40 { 41 for(int S2 = 0; S2 <= tot; S2++) 42 { 43 for(int u = 0; u < n; u++) if(dp[S1][S2][u] < INF) 44 { 45 int& now = dp[S1][S2][u]; //当前状态 46 int v, time; 47 for(int i = 0; i < k; i++) if(!(S1 & (1 << i))) 48 {//考虑下一次要去的景点 49 v = p[i]; 50 time = d[u][v]; 51 if(S2 & (1 << i)) time += ft[i]; 52 else time += t[i]; 53 int& nxt = dp[S1|(1<<i)][S2|state[v]][v]; 54 nxt = min(nxt, now + time); 55 } 56 57 for(v = 0; v < n; v++) 58 {//下一次可能去的地点,因为只是为了获得门票,所以不用排队进去参观 59 time = d[u][v]; 60 int& nxt = dp[S1][S2|state[v]][v]; 61 nxt = min(nxt, now + time); 62 } 63 } 64 } 65 } 66 67 for(int S2 = 0; S2 <= tot; S2++) ans = min(ans, dp[tot][S2][0]); 68 } 69 70 int main() 71 { 72 int T; scanf("%d", &T); 73 for(int kase = 1; kase <= T; kase++) 74 { 75 init(); 76 scanf("%d%d%d", &n, &m, &k); 77 //顶点标号从0开始 78 while(m--) 79 { 80 int u, v, dist; 81 scanf("%d%d%d", &u, &v, &dist); 82 u--; v--; 83 d[u][v] = d[v][u] = dist; 84 } 85 floyd(); 86 87 for(int i = 0; i < k; i++) 88 { 89 int num; 90 scanf("%d%d%d%d", &p[i], &t[i], &ft[i], &num); 91 p[i]--; 92 while(num--) { int x; scanf("%d", &x); x--; state[x] |= (1 << i); } 93 } 94 95 ans = INF; 96 DP(); 97 printf("Case #%d: %d\n", kase, ans); 98 } 99 100 return 0; 101 }
3832 Earth Hour 三点连通(斯坦纳树)
原来这叫斯坦纳树?
将三个点最为源点,跑三遍最短路。最短的路径上不会有重点,因为有重点的话,那它一定不是最短的。
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 #include <cmath> 6 #include <queue> 7 using namespace std; 8 9 const int maxn = 200 + 10; 10 const int INF = 10000000; 11 12 int n; 13 int dis[maxn][maxn]; 14 double x[maxn], y[maxn], r[maxn]; 15 16 bool connect(int i, int j) 17 { 18 double dx = x[i] - x[j]; 19 double dy = y[i] - y[j]; 20 double dist = sqrt(dx * dx + dy * dy); 21 return dist <= r[i] + r[j]; 22 } 23 24 void build_graph() 25 { 26 memset(dis, 0, sizeof(dis)); 27 for(int i = 0; i < n; i++) 28 for(int j = 0; j < i; j++) 29 dis[i][j] = dis[j][i] = connect(i, j) ? 1 : 0; 30 } 31 32 int d[3][maxn]; 33 bool inq[maxn]; 34 35 void SPFA(int s, int d[]) 36 { 37 memset(inq, false, sizeof(inq)); 38 inq[s] = true; 39 for(int i = 0; i < n; i++) d[i] = INF; 40 d[s] = 0; 41 queue<int> Q; 42 Q.push(s); 43 44 while(!Q.empty()) 45 { 46 int u = Q.front(); Q.pop(); 47 inq[u] = false; 48 for(int v = 0; v < n; v++) if(dis[u][v]) 49 { 50 if(d[v] > d[u] + 1) 51 { 52 d[v] = d[u] + 1; 53 if(!inq[v]) { inq[v] = true; Q.push(v); } 54 } 55 } 56 } 57 } 58 59 int main() 60 { 61 int T; scanf("%d", &T); 62 while(T--) 63 { 64 scanf("%d", &n); 65 for(int i = 0; i < n; i++) scanf("%lf%lf%lf", x + i, y + i, r + i); 66 build_graph(); 67 68 for(int s = 0; s < 3; s++) SPFA(s, d[s]); 69 70 int t = INF; 71 for(int u = 0; u < n; u++) t = min(t, d[0][u] + d[1][u] + d[2][u]); 72 if(t == INF) { puts("-1"); continue; } 73 printf("%d\n", n - t - 1); 74 } 75 76 77 return 0; 78 }
3873 Invade the Mars Dij变体,带保护的最短路
要想到达一个点,得先到达保护这个点的所有点。
好题,极力推荐!
题解
1 #include <cstdio> 2 #include <algorithm> 3 #include <cstring> 4 #include <queue> 5 #include <vector> 6 #include <map> 7 #define MP make_pair 8 using namespace std; 9 typedef long long LL; 10 typedef pair<LL, int> PII; 11 12 const int maxn = 3000 + 10; 13 const LL INF = 0x3f3f3f3f3f3f3f3f; 14 15 int n, m; 16 int deg[maxn]; //城市x的被保护度 17 LL time[maxn]; //所有保护x的城市全部被攻占的最早时间 18 vector<int> pro[maxn]; //城市x所保护的城市 19 20 struct Edge 21 { 22 int from, to; 23 LL dist; 24 Edge(int u, int v, LL d):from(u), to(v), dist(d) {} 25 }; 26 27 vector<Edge> edges; 28 vector<int> G[maxn]; 29 30 void init() 31 { 32 for(int i = 1; i <= n; i++) { G[i].clear(); pro[i].clear(); } 33 edges.clear(); 34 } 35 36 void AddEdge(int u, int v, LL d) 37 { 38 edges.push_back(Edge(u, v, d)); 39 int sz = edges.size(); 40 G[u].push_back(sz - 1); 41 } 42 43 LL d[maxn]; 44 bool done[maxn]; 45 46 void dijkstra() 47 { 48 memset(time, 0, sizeof(time)); 49 memset(d, 0x3f, sizeof(d)); 50 d[1] = 0; 51 memset(done, false, sizeof(done)); 52 priority_queue<PII, vector<PII>, greater<PII> > Q; 53 Q.push(MP(0LL, 1)); 54 55 while(!Q.empty()) 56 { 57 PII x = Q.top(); Q.pop(); 58 int u = x.second; 59 if(done[u]) continue; 60 done[u] = true; 61 62 for(int i = 0; i < pro[u].size(); i++) 63 { 64 int v = pro[u][i]; 65 deg[v]--; 66 time[v] = max(time[v], d[u]); 67 if(!deg[v] && d[v] < INF) 68 { 69 d[v] = max(d[v], time[v]); 70 Q.push(MP(d[v], v)); 71 } 72 } 73 74 for(int i = 0; i < G[u].size(); i++) 75 { 76 Edge& e = edges[G[u][i]]; 77 int v = e.to; 78 if(d[v] > d[u] + e.dist) 79 { 80 d[v] = max(d[u] + e.dist, time[v]); 81 if(!deg[v]) Q.push(MP(d[v], v)); 82 } 83 } 84 } 85 } 86 87 int main() 88 { 89 int T; scanf("%d", &T); 90 while(T--) 91 { 92 scanf("%d%d", &n, &m); 93 init(); 94 95 //build graph 96 while(m--) 97 { 98 int u, v; 99 LL d; 100 scanf("%d%d%I64d", &u, &v, &d); 101 AddEdge(u, v, d); 102 } 103 104 for(int i = 1; i <= n; i++) 105 { 106 scanf("%d", deg + i); 107 int x; 108 for(int j = 0; j < deg[i]; j++) { scanf("%d", &x); pro[x].push_back(i); } 109 } 110 111 dijkstra(); 112 113 printf("%I64d\n", d[n]); 114 } 115 116 return 0; 117 }
4063 Aircraft 几何构图 最短路(思路简单,就是代码有点难写)
两两圆求交点,如果两点之间全部被圆所覆盖,说明两点可达。
可以先求出线段和圆的所有交点,排个序,然后逐段判断线段是否被某个圆所覆盖。
1 /* 2 两两求出圆的交点,然后把这些点构图,求一遍最短路。 3 两个点可达,当且仅当整个线段都被圆所覆盖。 4 判断圆能被覆盖,可以求出线段和所有圆的交点,然后排个序,逐段判断。 5 */ 6 //#define DEBUG 7 #include <cstdio> 8 #include <cstring> 9 #include <algorithm> 10 #include <cmath> 11 #include <vector> 12 #include <queue> 13 using namespace std; 14 15 const int maxn = 1000; 16 const double INF = 1e10; 17 const double eps = 1e-6; 18 int n, sz; 19 20 int dcmp(double x) 21 { 22 if(fabs(x) < eps) return 0; 23 return x < 0 ? -1 : 1; 24 } 25 26 struct Point 27 { 28 double x, y; 29 Point(double x = 0, double y = 0):x(x), y(y) {} 30 }; 31 32 typedef Point Vector; 33 34 Point operator + (const Point& A, const Point& B) 35 { return Point(A.x + B.x, A.y + B.y); } 36 37 Point operator - (Point A, Point B) 38 { return Point(A.x - B.x, A.y - B.y); } 39 40 Point operator * (const Point& A, double p) 41 { return Point(A.x * p, A.y * p); } 42 43 Point operator / (const Point& A, double p) 44 { return Point(A.x / p, A.y / p); } 45 46 bool operator < (const Point& A, const Point& B) 47 { return A.x < B.x || (A.x == B.x && A.y < B.y); } 48 49 bool operator == (const Point& A, const Point& B) 50 { return dcmp(A.x - B.x) == 0 && dcmp(A.y - B.y) == 0; } 51 52 double Dot(Vector A, Vector B) 53 { return A.x * B.x + A.y * B.y; } 54 55 double Length(Vector A) 56 { 57 return sqrt(A.x*A.x + A.y*A.y); 58 } 59 60 double angle(Vector A) 61 { return atan2(A.y, A.x); } 62 63 struct Circle 64 { 65 Point c; 66 double r; 67 68 Circle() {} 69 Circle(Point c, double r):c(c), r(r) {} 70 71 Point point(double ang) 72 { return Point(c.x + r * cos(ang), c.y + r * sin(ang)); } 73 74 }circles[maxn]; 75 76 struct Line 77 { 78 Point p; 79 Vector v; 80 double ang; 81 82 Line() {} 83 Line(Point p, Vector v):p(p), v(v) { ang = atan2(v.y, v.x); } 84 85 Point point(double t) { return p + v * t; } 86 87 }; 88 89 void getCircleCircleIntersection(Circle C1, Circle C2, vector<Point>& sol) 90 {//求圆和圆的交点 91 double d = Length(C1.c - C2.c); 92 93 if(dcmp(d) == 0) return; 94 if(dcmp(C1.r + C2.r - d) < 0) return; 95 if(dcmp(fabs(C1.r - C2.r) - d) > 0) return; 96 97 double a = angle(C2.c - C1.c); 98 double da = acos((C1.r*C1.r + d*d - C2.r*C2.r) / (2.0 * C1.r * d)); 99 Point p1 = C1.point(a + da), p2 = C1.point(a - da); 100 sol.push_back(p1); 101 if(p1 == p2) return; 102 sol.push_back(p2); 103 } 104 105 void getCircleLineIntersection(Line L, Circle C, vector<Point>& sol) 106 {//求线段和圆的交点 107 double a = L.v.x, b = L.p.x - C.c.x, c = L.v.y, d = L.p.y - C.c.y; 108 double e = a*a + c*c, f = 2.0*(a*b + c*d), g = b*b + d*d - C.r*C.r; 109 double delta = f*f - 4.0*e*g; 110 111 if(dcmp(delta) < 0) return; 112 113 if(dcmp(delta) == 0) 114 { 115 double t = -f / (2.0 * e); 116 if(dcmp(t) >= 0 && dcmp(t - 1) <= 0) 117 sol.push_back(L.point(t)); 118 } 119 120 double t1 = (-f - sqrt(delta)) / (2 * e); 121 if(dcmp(t1) >= 0 && dcmp(t1 - 1) <= 0) 122 sol.push_back(L.point(t1)); 123 124 double t2 = (-f + sqrt(delta)) / (2 * e); 125 if(dcmp(t2) >= 0 && dcmp(t2 - 1) <= 0) 126 sol.push_back(L.point(t2)); 127 } 128 129 vector<Point> p; 130 131 bool SegmentInCircle(const Point& A, const Point& B) 132 {//线段在圆内,也就是两个端点都要在某个圆内 133 bool ok = false; 134 for(int i = 0; i < n; i++) 135 { 136 Circle& C = circles[i]; 137 if(dcmp(Length(A - C.c) - C.r) <= 0 138 && dcmp(Length(B - C.c) - C.r) <= 0) 139 { 140 ok = true; 141 break; 142 } 143 } 144 return ok; 145 } 146 147 bool SegmentBeCoverd(Point A, Point B) 148 {//判断这条路线能否走通,写就是整条线段都被若干个圆所覆盖 149 vector<Point> inter; 150 inter.push_back(A); 151 inter.push_back(B); 152 Line L(A, B - A); 153 for(int i = 0; i < n; i++) 154 getCircleLineIntersection(L, circles[i], inter); 155 156 sort(inter.begin(), inter.end()); 157 158 int sz = inter.size(); 159 for(int i = 0; i < sz - 1; i++) 160 if(!SegmentInCircle(inter[i], inter[i + 1])) 161 return false; 162 163 return true; 164 } 165 166 struct Edge 167 { 168 int from, to; 169 double dist; 170 Edge(int u, int v, double d):from(u), to(v), dist(d) {} 171 }; 172 173 vector<Edge> edges; 174 vector<int> G[maxn]; 175 176 void init() 177 { 178 p.clear(); 179 edges.clear(); 180 for(int i = 0; i < sz; i++) G[i].clear(); 181 } 182 183 void AddEdge(int u, int v, double d) 184 { 185 edges.push_back(Edge(u, v, d)); 186 edges.push_back(Edge(v, u, d)); 187 int sz = edges.size(); 188 G[u].push_back(sz - 2); 189 G[v].push_back(sz - 1); 190 } 191 192 double d[maxn]; 193 bool inq[maxn]; 194 195 void SPFA() 196 { 197 for(int i = 0; i < sz; i++) d[i] = INF; 198 d[0] = 0; 199 memset(inq, false, sizeof(inq)); 200 inq[0] = true; 201 queue<int> Q; 202 Q.push(0); 203 204 while(!Q.empty()) 205 { 206 int u = Q.front(); Q.pop(); 207 inq[u] = false; 208 for(int i = 0; i < G[u].size(); i++) 209 { 210 Edge& e = edges[G[u][i]]; 211 int v = e.to; 212 if(d[v] > d[u] + e.dist) 213 { 214 d[v] = d[u] + e.dist; 215 if(!inq[v]) { inq[v] = true; Q.push(v); } 216 } 217 } 218 } 219 } 220 221 int main() 222 { 223 int T; scanf("%d", &T); 224 for(int kase = 1; kase <= T; kase++) 225 { 226 scanf("%d", &n); 227 228 init(); 229 230 for(int i = 0; i < n; i++) 231 { 232 double x, y, r; 233 scanf("%lf%lf%lf", &x, &y, &r); 234 Point p(x, y); 235 circles[i] = Circle(p, r); 236 } 237 238 p.push_back(circles[0].c); 239 p.push_back(circles[n - 1].c); 240 241 for(int i = 0; i < n; i++) 242 for(int j = 0; j < i; j++) 243 getCircleCircleIntersection(circles[i], circles[j], p); 244 sz = p.size(); 245 246 for(int i = 0; i < sz; i++) 247 { 248 for(int j = 0; j < i; j++) 249 { 250 double d = Length(p[i] - p[j]); 251 252 if(SegmentBeCoverd(p[i], p[j])) 253 AddEdge(i, j, d); 254 } 255 } 256 257 SPFA(); 258 259 printf("Case %d: ", kase); 260 if(dcmp(d[1] == INF)) puts("No such path."); 261 else printf("%.4f\n", d[1]); 262 } 263 264 return 0; 265 }
hdu4179 Difficult Routes 带限制最短路
建一个正图和反图,分别求出源点到各点的最短距离,和各点到源点的最短距离。
枚举难度为d的边,求最小值。
1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 #include <queue> 5 #include <vector> 6 #include <cmath> 7 using namespace std; 8 9 const int maxn = 10000 + 10; 10 const int maxm = 30000 + 10; 11 const double INF = 1e8; 12 const double eps = 1e-6; 13 14 int dcmp(double x) 15 { 16 if(fabs(x) < eps) return 0; 17 return x < 0 ? -1 : 1; 18 } 19 20 int n, m, s, t, D; 21 22 int u[maxm], v[maxm]; 23 double x[maxn], y[maxn], z[maxn]; 24 vector<int> eq; 25 26 struct Edge 27 { 28 int from, to; 29 double dist; 30 Edge(int u, int v, double d):from(u), to(v), dist(d) {} 31 }; 32 33 vector<Edge> edges[2]; 34 vector<int> G[2][maxn]; 35 36 void init() 37 { 38 for(int i = 1; i <= n; i++) { G[0][i].clear(); G[1][i].clear(); } 39 edges[0].clear(); 40 edges[1].clear(); 41 } 42 43 void AddEdge(int num, int u, int v, double d) 44 { 45 edges[num].push_back(Edge(u, v, d)); 46 int sz = edges[num].size(); 47 G[num][u].push_back(sz - 1); 48 } 49 50 void Dist(int u, int v, double& run, double& d) 51 { 52 double dx = x[u] - x[v]; 53 double dy = y[u] - y[v]; 54 double dz = z[u] - z[v]; 55 d = sqrt(dx*dx + dy*dy + dz*dz); 56 run = sqrt(dx*dx + dy*dy); 57 } 58 59 inline int Difficulty(int u, int v, double run) 60 { 61 if(z[u] >= z[v]) return 0; 62 return (int) floor(100.0 * (z[v] - z[u]) / run); 63 } 64 65 double ds[maxn], dt[maxn]; 66 bool inq[maxn]; 67 68 void SPFA(int num, int s, double d[]) 69 { 70 for(int i = 1; i <= n; i++) d[i] = INF; 71 d[s] = 0; 72 memset(inq, false, sizeof(inq)); 73 inq[s] = true; 74 queue<int> Q; 75 Q.push(s); 76 77 while(!Q.empty()) 78 { 79 int u = Q.front(); Q.pop(); 80 inq[u] = false; 81 for(int i = 0; i < G[num][u].size(); i++) 82 { 83 Edge& e = edges[num][G[num][u][i]]; 84 int v = e.to; 85 if(d[v] > d[u] + e.dist) 86 { 87 d[v] = d[u] + e.dist; 88 if(!inq[v]) { inq[v] = true; Q.push(v); } 89 } 90 } 91 } 92 } 93 94 int main() 95 { 96 //freopen("in.txt", "r", stdin); 97 98 while(scanf("%d%d", &n, &m) == 2) 99 { 100 if(n == 0 && m == 0) break; 101 102 for(int i = 1; i <= n; i++) scanf("%lf%lf%lf", x + i, y + i, z + i); 103 for(int i = 1; i <= m; i++) scanf("%d%d", u + i, v + i); 104 scanf("%d%d%d", &s, &t, &D); 105 106 init(); 107 eq.clear(); 108 for(int i = 1; i <= m; i++) 109 { 110 double run, d; 111 Dist(u[i], v[i], run, d); 112 113 int diffi = Difficulty(u[i], v[i], run); 114 if(diffi <= D) 115 { 116 AddEdge(0, u[i], v[i], d); 117 AddEdge(1, v[i], u[i], d); 118 if(diffi == D) { int sz = edges[0].size(); eq.push_back(sz - 1); } 119 } 120 121 diffi = Difficulty(v[i], u[i], run); 122 if(diffi <= D) 123 { 124 AddEdge(0, v[i], u[i], d); 125 AddEdge(1, u[i], v[i], d); 126 if(diffi == D) { int sz = edges[0].size(); eq.push_back(sz - 1); } 127 } 128 } 129 130 SPFA(0, s, ds); 131 SPFA(1, t, dt); 132 133 double ans = INF; 134 for(int i = 0; i < eq.size(); i++) 135 { 136 Edge& e = edges[0][eq[i]]; 137 int u = e.from, v = e.to; 138 ans = min(ans, ds[u] + e.dist + dt[v]); 139 } 140 141 if(dcmp(ans - INF) == 0) puts("None"); 142 else printf("%.1f\n", ans); 143 } 144 145 return 0; 146 }
待续……