赞
踩
样例输入:
- 5 6 1 5
- 1 2 1
- 2 3 2
- 3 4 3
- 4 1 5
- 3 5 4
- 4 5 1
样例输出:
- 11 6
- Lose!
分析:对于第二种选择显然直接跑一边最短路就可以了,这里就不多说了,下面主要说一下第一种选择。我一开始以为直接跑一个最短路就行,对于第一种说的回到s点,直接枚举与s存在直接边的j,求一个min(d[j]+dis[j][s])即可,但是发现样例都不对,模拟了一下发现存在重边,也就是说从s到j求最短路时经过了直接边s->j,所以就会产生错误,然后就发现思路错了,我就尝试了一下跑多次最短路,也就是对于每一个和s有直接边的j,我都直接跑一边最短路,但是这次最短路不能经过s->j这条边,然后我们再求一下d[j]+dis[j][s],最后取一个最小值即可。交了之后有一个超时,但是看了一下边数和点数,边数是1e5,点数是500,因为我写的是堆优化版的dijkstra,复杂度是O(mlogm),而这道题给的是一个稠密图,所以最好是用朴素版的最短路,直接换成朴素版的就能过了。复杂度是O(n^3)
细节见代码:
- #include<cstdio>
- #include<iostream>
- #include<algorithm>
- #include<cstring>
- #include<map>
- #include<queue>
- #include<vector>
- #include<cmath>
- using namespace std;
- const int N=1e6+10;
- typedef pair<int,int>PII;
- int d[N],n;
- int p[503][503];
- bool vis[N];
- void dijkstra(int x,int u,int v)
- {
- memset(vis,false,sizeof vis);
- memset(d,0x3f,sizeof d);
- d[x]=0;
- for(int i=1;i<n;i++)
- {
- int t=-1;
- for(int j=1;j<=n;j++)
- if(!vis[j]&&(t==-1||d[t]>d[j])) t=j;
- vis[t]=true;
- for(int j=1;j<=n;j++)
- {
- if(t==u&&j==v) continue;
- if(d[j]>d[t]+p[t][j]) d[j]=d[t]+p[t][j];
- }
- }
- }
- int main()
- {
- int m,s,t;
- cin>>n>>m>>s>>t;
- memset(p,0x3f,sizeof p);
- for(int i=1;i<=m;i++)
- {
- int u,v,t;
- scanf("%d%d%d",&u,&v,&t);
- p[u][v]=p[v][u]=t;
- }
- int t1=0x3f3f3f3f;
- for(int i=1;i<=n;i++)
- {
- if(i==s||p[i][s]==0x3f3f3f3f) continue;
- dijkstra(s,s,i);
- t1=min(t1,d[i]+p[i][s]);
- }
- dijkstra(s,0,0);
- int t2=d[t];
- if(t1==0x3f3f3f3f) printf("-1 ");
- else printf("%d ",t1);
- if(t2==0x3f3f3f3f) printf("-1\n");
- else printf("%d\n",t2);
- if(t1!=0x3f3f3f3f&&t1<t2) printf("Win!");
- else printf("Lose!");
- return 0;
- }

Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。