POJ 3268 Silver Cow Party (Dijkstra)

这道题和1502有些像,不同的是,1502只要找出起点到各个点的最短路径,然后判断是不是相对最长路径就能AC;这道题除了要找出起点到各点的最短路,还要求得各点到起点的最短路,然后做个和,表示来自不同农场的牛需要走的总路程

还有一个不同,本题给定的点较多,Floyd会超时,于是考虑采用Dijkstra。

 

 1 #include<iostream>
2 using namespace std;
3 #define CLR(a) memset(a,0,sizeof(a))
4 const int INF = 1 << 29;
5 int n, m, x, vis[1005], dis[1005], map[1005][1005], sum[1005] = {0};
6
7 void init()
8 {
9 for(int i = 1; i <= n; i++)
10 for(int j = 1; j <= n; j++)
11 map[i][j] = (i == j) ? 0 : INF;
12 }
13
14 void reversal()
15 {
16 //将矩阵转置
17 //如果原来的地图计算得到从n到各点的最短路径
18 //那么经过转置后重新计算,就是各点到(返回至)n的最短路径
19 for(int i = 1; i <= n; i++)
20 for(int j = 1; j < i; j++)
21 map[i][j] ^= map[j][i] ^= map[i][j] ^= map[j][i];
22 }
23
24 void dijkstra()
25 {
26 int next;
27 CLR(vis);
28 CLR(dis);
29 for(int i = 1; i <= n; i++)
30 {
31 //dis保存从起点到终点的最短路
32 dis[i] = map[x][i];
33 }
34 vis[x] = 1; //起始点已访问
35 next = x;
36 for(int i = 1; i < n; i++)
37 {
38 int min = INF;
39 for(int j = 1; j <= n; j++)
40 {
41 if(!vis[j] && dis[j] < min)
42 {
43 min = dis[j];
44 next = j;
45 }
46 }
47 //sum中记录的是起点到各点的最短路程与该点返回起点的最短路程之和
48 sum[next] += min;
49 //遍历和上一点有关系的所有顶点,确定上一个点到next是最短,贪心思想的体现
50 vis[next] = 1;
51 for(int j = 1; j <= n; j++)
52 {
53 //因为next已被标记访问,所以遇到dis[next]不会被更新,dis[next]值得到保存
54 //然后,从next出发,到与其连接的所有点,判断从next出发是不是其最短路(如果以前有使用过)
55 //推广,当所有点被标记完毕,这时候dis数组中保存的就是起点到各顶点的最短路径
56 if(!vis[j] && dis[next] + map[next][j] < dis[j])
57 {
58 dis[j] = dis[next] + map[next][j];
59 }
60 }
61 }
62 }
63
64 int main()
65 {
66 int maxdis = 0;
67 scanf("%d%d%d", &n, &m, &x);
68 init();
69 while(m--)
70 {
71 int a, b, t;
72 scanf("%d%d%d", &a, &b, &t);
73 if(t < map[a][b])
74 map[a][b] = t;
75 }
76 dijkstra();
77 reversal();
78 dijkstra();
79 for(int i = 1; i <= n; i++)
80 maxdis = max(maxdis, sum[i]);
81 printf("%d\n", maxdis);
82 return 0;
83 }

 

posted @ 2012-02-16 22:39  dgsrz  阅读(146)  评论(0编辑  收藏  举报