最短路

模板。

dijkstra。邻接矩阵+函数。

 1 #include <iostream>
 2 #include <cstring>
 3 #include <cstdio>
 4 using namespace std;
 5 
 6 int n, m, a, b, c;
 7 
 8 #define maxn 110
 9 #define INF 10000000
10 int w[maxn][maxn];
11 int d[maxn];
12 bool v[maxn];
13 //int fa[maxn];//如果需要记录路径。
14 //点从1开始
15 void ini(){
16     for (int i = 1; i <= n; i++)
17         for (int j = 1; j <= n; j++)
18             w[i][j] = INF;
19     //如果需要记录路径
20 //    for (int i = 1; i <= n; i++)
21 //        fa[i] = i;
22 }
23 
24 void dijkstra(int s){
25     memset(v, false, sizeof(v));
26     for (int i = 1; i <= n; i++)
27         d[i] = INF;
28     d[s] = 0;
29     //每次确定一个点到源点的最短路径。
30     for (int i = 0; i < n; i++){
31         int x, m = INF;
32         //找出该点及该点最短路径
33         for (int y = 1; y <= n; y++){
34             if(!v[y] && d[y] <= m)
35                 m = d[x = y];
36         }
37         //标记该点已找到最短路径
38         v[x] = true;
39         //用该点松弛其他点
40         for (int y = 1; y <= n; y++){
41             d[y] = min(d[y], d[x] + w[x][y]);
42             //如果要输出路径的话。将上面一行替换成下面四行。
43 //            if(d[y] > d[x] + w[x][y]){
44 //                d[y] = d[x] + w[x][y];
45 //                fa[y] = x;
46 //            }
47         }
48     }
49 }
50 
51 int main()
52 {
53     while(scanf("%d%d", &n,&m),n+m){
54         ini();
55 
56         for (int i = 0; i < m; i++){
57             scanf("%d%d%d", &a, &b, &c);
58             if(w[a][b] > c)
59                 w[a][b] = w[b][a] = c;
60         }
61 
62         dijkstra(1);
63 
64         printf("%d\n", d[n]);
65     }
66     return 0;
67 }
68 //HDU2544无向正权图。

 dijkstra。邻接表+优先队选边时优化(n->logn)。

  1 #include <iostream>
  2 #include <cstdio>
  3 #include <vector>
  4 #include <cstring>
  5 #include <queue>
  6 using namespace std;
  7 
  8 int u, v, w;
  9 
 10 #define maxn 110
 11 #define INF 10000000
 12 //点号从0开始,边号从0开始。
 13 
 14 //
 15 struct Edge{
 16     int from, to, dist;
 17     Edge(int u, int v, int d):from(u),to(v),dist(d){}
 18 };
 19 
 20 //
 21 struct HeapNode{
 22     int d, u;
 23     bool operator < (const HeapNode& rhs) const{
 24         return d > rhs.d;
 25     }
 26 };
 27 
 28 
 29 int n, m;
 30 
 31 vector<Edge> edges;
 32 vector<int> G[maxn];
 33 bool done[maxn];
 34 int d[maxn];
 35 //记录路径
 36 //int p[maxn];
 37 
 38 void init(){
 39     for (int i = 0; i < n; i++)
 40         G[i].clear();
 41     edges.clear();
 42     //初始化路径
 43 //    for (int i = 0; i < n; i++)
 44 //        p[i] = i;
 45 }
 46 
 47 void AddEdge(int from, int to, int dist){
 48     edges.push_back(Edge(from, to, dist));
 49     int cnt = edges.size();
 50     G[from].push_back(cnt-1);//边从0开始标号
 51 }
 52 
 53 void dijkstra(int s){
 54     priority_queue<HeapNode> Q;
 55     for(int i = 0; i < n; i++)
 56         d[i] = INF;
 57     d[s] = 0;
 58     memset(done, false, sizeof(done));
 59     Q.push((HeapNode){0,s});
 60 
 61     //直到没有新的最短路产生。
 62     while(!Q.empty()){
 63         HeapNode x = Q.top();
 64         Q.pop();
 65         int u = x.u;
 66 
 67         if(done[u]) continue;//有可能一个点多次入队,如果已经找到了该点最短路,直接continue
 68         done[u] = true;
 69 
 70         //遍历该点的每条边
 71         for (int i = 0; i < G[u].size(); i++){
 72             Edge& e = edges[G[u][i]];
 73             //松弛该边上的点
 74             if(d[e.to] > d[u] + e.dist){
 75                 d[e.to] = d[u] + e.dist;
 76                 //记录路径
 77 //                p[e.to] = G[u][i];
 78                 //入队,等待选最短路,松弛其他点。
 79                 Q.push((HeapNode){d[e.to], e.to});
 80             }
 81         }
 82     }
 83 }
 84 
 85 int main()
 86 {
 87     while(~scanf("%d%d", &n, &m), n+m){
 88         init();
 89         for (int i = 0; i < m; i++){
 90             scanf("%d%d%d", &u,&v,&w);
 91             u--;
 92             v--;
 93             AddEdge(u,v,w);
 94             AddEdge(v,u,w);
 95         }
 96         dijkstra(0);
 97         printf("%d\n", d[n-1]);
 98     }
 99     return 0;
100 }
101 //HDU2544无向正权

 spfa

 1 #include <iostream>
 2 #include <queue>
 3 #include <vector>
 4 #include <cstring>
 5 #include <cstdio>
 6 
 7 using namespace std;
 8 
 9 #define maxn 110
10 #define INF 10000000
11 int u, v, w;
12 //点序号从0开始,边序号从0开始。
13 struct Edge{
14     int from, to, dist;
15     Edge(int u, int v, int w):from(u),to(v),dist(w){}
16 };
17 
18 int n, m;
19 vector<Edge> edges;
20 vector<int> G[maxn];
21 bool inq[maxn];//是否在队列中
22 int d[maxn];
23 //int p[maxn];//记录路径
24 int cnt[maxn];//进队次数
25 
26 void init(){
27     for (int i = 0; i < n; i++)
28         G[i].clear();
29     edges.clear();
30 //    for (int i = 0; i < n; i++)//初始化路径
31 //        p[i] = i;
32 }
33 
34 //无向图,调用2次加边函数。去一条回一条。
35 void AddEdge(int from, int to, int dist){
36     edges.push_back((Edge){from, to, dist});
37     int cont = edges.size();
38     G[from].push_back(cont-1);
39 }
40 
41 bool spfa(int s){
42     //记录点的队列
43     queue<int> Q;
44     memset(inq, 0, sizeof(inq));
45     memset(cnt, 0, sizeof(cnt));
46 
47     for(int i = 0; i < n; i++)
48         d[i] = INF;
49     d[s] = 0;
50     inq[s] = true;
51     Q.push(s);
52 
53     while(!Q.empty()){//取出一个点,松弛该点每条边
54         int u = Q.front();
55         Q.pop();
56         inq[u] = false;
57         for (int i = 0; i < G[u].size(); i++){
58             Edge& e = edges[G[u][i]];
59             //点u可达,判断是否能松弛e.to
60             if(d[u] < INF && d[e.to] > d[u] + e.dist){
61                 d[e.to] = d[u] + e.dist;
62 //                p[e.to] = G[u][i];//记录路径
63                 if(!inq[e.to]){
64                     Q.push(e.to);
65                     inq[e.to] = true;
66                     if(++cnt[e.to] > n)//每一次入队代表被松弛了一次,一共n个点,每个点最多被松弛n-1次。
67                         return false;
68                 }
69             }
70         }
71     }
72     return true;
73 }
74 
75 int main()
76 {
77     while(scanf("%d%d", &n, &m),n+m){
78         init();
79         for (int i = 0; i < m; i++){
80             scanf("%d%d%d", &u, &v, &w);
81             u--;
82             v--;
83             AddEdge(u, v, w);
84             AddEdge(v, u, w);
85         }
86         spfa(0);
87         printf("%d\n", d[n-1]);
88     }
89     return 0;
90 }//HDU2544无向正权

 floyd

 1 #include <iostream>
 2 #include <cstdio>
 3 using namespace std;
 4 
 5 #define maxn 110
 6 #define INF 10000000
 7 int d[maxn][maxn];
 8 int n, m;
 9 int u, v, w;
10 
11 void ini(){
12     for (int i = 0; i < n; i++){
13         for (int j = 0; j < n; j++){
14             d[i][j] = INF;
15         }
16     }
17 }
18 
19 void floyd(){
20     for (int k = 0; k < n; k++)
21     for (int i = 0; i < n; i++)
22     for (int j = 0; j < n; j++)
23         d[i][j] = min(d[i][j], d[i][k]+d[k][j]);
24 }
25 
26 int main()
27 {
28     while(scanf("%d%d", &n, &m),n+m){
29         ini();
30         for (int i = 0; i < m; i++){
31             scanf("%d%d%d", &u, &v, &w);
32             u--;
33             v--;
34             d[u][v] = d[v][u] = w;//v到u的最短路就是边权。
35         }
36         floyd();
37         printf("%d\n", d[0][n-1]);
38     }
39     return 0;
40 }
41 //HDU2544无向正权

 

posted @ 2016-02-24 16:45  喷水小火龙  阅读(96)  评论(0)    收藏  举报