POJ 3268 Silver Cow Party (Dijkstra + 优先队列)
题意:由n个牧场,编号1到n。每个牧场有一头牛。现在在牧场x举办party,每头牛都去参加,然后再回到自己的牧场。牧场之间会有一些单向的路。每头牛都会让自己往返的路程最短。问所有牛当中最长的往返路程是多少。
思路:n最多到1000,floyd肯定超时。可以这样做,把图中所有的边先存起来,然后第一次用dijkstra求出以x为源点到每个点的最短距离。该最短距离为每头牛回家时的最短距离。然后建个新的图,将之前存的边反向加入图中。如之前有条从5到8距离为2的路,则此时向图中添加的边为从8到5距离为2的边。这样再次以x为源点求到每个点的最短距离,将两者相加,就是每头牛往返的最短距离了。求其中的最大值即可。
代码中的dijkstra算法用优先队列进行了优化。
1 #include<stdio.h> 2 #include<string.h> 3 #include<iostream> 4 #include<algorithm> 5 #include<queue> 6 #define maxn 1010 7 #define maxp 100010 8 #define inf 0x3f3f3f3f 9 using namespace std; 10 struct node 11 { 12 int v, w, next; 13 node(){} 14 node(int a,int b){v = a; w = b;} 15 bool operator < (const node &cmp) const 16 { 17 if (w == cmp.w) return v < cmp.v; 18 else return w > cmp.w; 19 } 20 }edge[maxp]; 21 int num_edge, head[maxn]; 22 void init_edge() 23 { 24 num_edge = 0; 25 memset(head, -1, sizeof(head)); 26 } 27 void addedge(int a,int b,int w) 28 { 29 edge[num_edge].v = b; 30 edge[num_edge].w = w; 31 edge[num_edge].next = head[a]; 32 head[a] = num_edge++; 33 } 34 int n, m, x, dis1[maxn], dis2[maxn]; 35 void dijkstra(int s, int dis[]) 36 { 37 for (int i = 1; i <= n; i++) 38 dis[i] = (i == s ? 0 : inf); 39 priority_queue<node> q; 40 q.push(node(s, dis[s])); 41 while (!q.empty()) 42 { 43 node u = q.top(); q.pop(); 44 for (int i = head[u.v]; i != -1; i = edge[i].next) 45 { 46 int v = edge[i].v; 47 if (dis[v] > u.w + edge[i].w) 48 { 49 dis[v] = u.w + edge[i].w; 50 q.push(node(v, dis[v])); 51 } 52 } 53 } 54 } 55 int e[maxp][3]; 56 int main() 57 { 58 //freopen("data.in", "r", stdin); 59 scanf("%d%d%d",&n, &m, &x); 60 { 61 init_edge(); 62 for (int i = 0; i < m; i++) 63 { 64 scanf("%d%d%d",&e[i][0],&e[i][1],&e[i][2]); 65 addedge(e[i][0], e[i][1], e[i][2]); 66 } 67 dijkstra(x, dis1); 68 init_edge(); 69 for (int i = 0; i < m; i++) 70 addedge(e[i][1], e[i][0], e[i][2]); 71 dijkstra(x, dis2); 72 int tmax = -inf; 73 for (int i = 1; i <= n; i++) 74 tmax = max(tmax, dis1[i] + dis2[i]); 75 printf("%d", tmax); 76 } 77 return 0; 78 }