【司雨寒】最短路专题总结

最近在刷郏老大博客上的最短路专题

 

【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 }
Dijkstra

 

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 }
Dijkstra

 

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 }
Dijkstra

 

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 }
Dijkstra

 

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 }
Dijkstra

 

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 }
Floyd

 

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 }
BFS

 

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 }
SPFA

 

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 }
Dijkstra
 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 }
SPFA

 

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 }
Dijkstra
 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 }
SPFA

 

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 }
Dijkstra
 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 }
SPFA

 

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 }
Floyd

 

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 }
SPFA

 

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 }
Floyd

 

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 }
Dijkstra

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 }
SPFA

 

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 }
Dijkstra

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 }
SPFA

 

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 }
Floyd

 

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 }
Dijkstra

 

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 }
Floyd

 

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 }
SPFA

 

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 }
Dijkstra

 

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 }
SPFA

 

待续……

你可能感兴趣的:(【司雨寒】最短路专题总结)