http://poj.org/problem?id=3268
每头牛都要去标号为X的农场参加一个party,农场总共有N个(标号为1-n),总共有M单向路联通,每头牛参加完party之后需要返回自己的农场,但是他们都想选一条最近的路,并且由于路是单向的,去的路和来的路选择可能不一样,问来去时间之和最大是多少?
这题等于给定了起点和终点,那么求出(d[x][i]+d[i][x])最大的那个即可。
开始错了几次,太不小心了,就是最后求最大值的时候,用了一个临时变量没置0,所以可能会导致错误。
1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 #include <algorithm> 5 #include <vector> 6 #include <queue> 7 #include <set> 8 #include <map> 9 #include <string> 10 #include <cmath> 11 #include <cstdlib> 12 #include <ctime> 13 using namespace std; 14 const int maxn= 1010; 15 const int INF = 1<<29; 16 struct edge{ 17 int to,cost; 18 edge(){} 19 edge(int x,int y) { 20 to=x; 21 cost=y; 22 } 23 }; 24 typedef pair<int,int>P; 25 26 int N,M,X; 27 vector<edge>G[maxn]; 28 int d[maxn]; 29 30 int dijkstra(int s,int t) { 31 priority_queue<P,vector<P>,greater<P> >que; 32 for(int i=0;i<=N;i++) d[i]=INF; 33 d[s]=0; 34 que.push(P(0,s)); 35 36 while(!que.empty()) { 37 P p=que.top(); que.pop(); 38 int v=p.second; 39 if(v==t) return d[t]; 40 if(d[v]<p.first) continue; 41 for(int i=0;i<G[v].size();i++) { 42 edge e=G[v][i]; 43 if(d[e.to]>d[v]+e.cost) { 44 d[e.to]=d[v]+e.cost; 45 que.push(P(d[e.to],e.to)); 46 } 47 } 48 } 49 } 50 51 int main() 52 { 53 //freopen("a.txt","r",stdin); 54 //freopen("b.txt","w",stdout); 55 int a,b,c; 56 while(~scanf("%d%d%d",&N,&M,&X)) { 57 for(int i=0;i<M;i++) { 58 scanf("%d%d%d",&a,&b,&c); 59 G[a].push_back(edge(b,c)); 60 } 61 int sum=0; 62 for(int i=1;i<=N;i++) { 63 sum=max(sum,dijkstra(i,X)+dijkstra(X,i)); 64 } 65 printf("%d ",sum); 66 } 67 return 0; 68 }
还有一种方法,首先求出点X到各个点i的最短路径,这就是奶牛返回的最短距离,然后把路径反向,在求点X到各个点i的最短距离,就是每个点到点X的最短距离。
最后把两个距离相交即可。
不过对于反向,不是很明白。
时间直接从600多ms降到60多ms。
1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 #include <algorithm> 5 #include <vector> 6 #include <queue> 7 #include <set> 8 #include <map> 9 #include <string> 10 #include <cmath> 11 #include <cstdlib> 12 #include <ctime> 13 using namespace std; 14 const int maxn= 1010; 15 const int INF = 1<<29; 16 struct edge{ 17 int to,cost; 18 edge(){} 19 edge(int x,int y) { 20 to=x; 21 cost=y; 22 } 23 }; 24 typedef pair<int,int>P; 25 26 int N,M,X; 27 vector<edge>G[maxn],RG[maxn]; 28 int d[maxn],rd[maxn]; 29 30 void dijkstra(int s) { 31 priority_queue<P,vector<P>,greater<P> >que; 32 for(int i=0;i<=N;i++) d[i]=INF; 33 d[s]=0; 34 que.push(P(0,s)); 35 36 while(!que.empty()) { 37 P p=que.top(); que.pop(); 38 int v=p.second; 39 if(d[v]<p.first) continue; 40 for(int i=0;i<G[v].size();i++) { 41 edge e=G[v][i]; 42 if(d[e.to]>d[v]+e.cost) { 43 d[e.to]=d[v]+e.cost; 44 que.push(P(d[e.to],e.to)); 45 } 46 } 47 } 48 } 49 50 int main() 51 { 52 //freopen("a.txt","r",stdin); 53 //freopen("b.txt","w",stdout); 54 int a,b,c; 55 scanf("%d%d%d",&N,&M,&X); 56 for(int i=0;i<M;i++) { 57 scanf("%d%d%d",&a,&b,&c); 58 G[a].push_back(edge(b,c)); 59 RG[b].push_back(edge(a,c)); //存储 反向边 60 } 61 dijkstra(X); //第一次 dijkstra 是求X到各个点的距离 62 //for(int i=1;i<=N;i++) printf("%d ",d[i]); 63 for(int i=1;i<=N;i++) G[i]=RG[i]; //然后 把反向存储的边赋值给 G 64 // for(int i=1;i<=N;i++) { 65 // for(int j=0;j<G[i].size();j++) 66 // cout<<G[i][j].to<<" "<<G[i][j].cost<<endl; 67 //} 68 memcpy(rd,d,sizeof(d)); //把第一次的 最短距离 保存 69 70 dijkstra(X); //反向的 dijkstra 求出每个点到X的最短距离 71 //for(int i=1;i<=N;i++) printf("%d ",d[i]); 72 int sum=0; //枚举最大和 73 for(int i=1;i<=N;i++) { 74 sum=max(sum,d[i]+rd[i]); 75 } 76 printf("%d ",sum); 77 return 0; 78 }