LA 6891 Money Transfers(最短路)
Posted 谦谦君子,陌上其华
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了LA 6891 Money Transfers(最短路)相关的知识,希望对你有一定的参考价值。
https://vjudge.net/problem/UVALive-6891
题意:
给定一个加权无向图,还有起点和终点,现在有个SWERC公司,拥有图中的m个顶点,现在可以使图中的每一条边都加上k后求最短路,使得最短路上的点都包括在SWERC公司拥有的m个顶点中。求k的最大值。
思路:
对于k,采用二分法枚举。
我们可以求出起点到终点的最短路径,然后判断这些点是否都在SWERC公司当中即可。
还有容易错的一点!!
每个图中可能不止一条最短路,也许一条最短路时满足条件的,但是另外的是不满足的,那么这样也是不行的。
对于这个可以这样解决,在dijkstra算法当中,每次选择最短边加入时,在长度相同的情况下,我们优先选择不在SWERC公司中的顶点,这样这个问题就解决了。
1 #include<iostream> 2 #include<algorithm> 3 #include<cstring> 4 #include<cstdio> 5 #include<sstream> 6 #include<vector> 7 #include<stack> 8 #include<queue> 9 #include<cmath> 10 #include<map> 11 using namespace std; 12 typedef long long ll; 13 typedef pair<int,long long> pll; 14 const int INF=0x3f3f3f3f; 15 const int maxn=1000+5; 16 17 int n,p,src,dst,m; 18 19 int sw[maxn]; 20 ll d[maxn]; 21 int vis[maxn]; 22 int path[maxn]; 23 24 vector<pll> G[maxn]; 25 26 bool dijkstra(ll x) 27 { 28 memset(d,INF,sizeof(d)); 29 memset(vis,0,sizeof(vis)); 30 memset(path,0,sizeof(path)); 31 32 d[src]=0; 33 34 for(int i=1;i<=n;i++) 35 { 36 ll MIN =20000000000000LL; 37 int pos; 38 for(int j=1;j<=n;j++) 39 { 40 if(d[j]<=MIN && !vis[j]) 41 { 42 if(d[j]==MIN) {if(sw[j]==0) pos=j;} //这个很重要,优先考虑不在SW中的点 43 else 44 { 45 MIN=d[j]; 46 pos=j; 47 } 48 } 49 } 50 51 if(MIN==20000000000000LL) break; 52 if(pos==dst) break; 53 vis[pos]=1; 54 55 for(int j=0;j<G[pos].size();j++) 56 { 57 int v=G[pos][j].first; 58 if(vis[v]) continue; 59 ll w=G[pos][j].second+x; 60 if(d[pos]+w<d[v]) 61 { 62 d[v]=d[pos]+w; 63 path[v]=pos; 64 } 65 } 66 } 67 68 for(int i=dst;path[i]!=0;i=path[i]) 69 if(sw[i]==0) return false; 70 71 return true; 72 } 73 74 75 int main() 76 { 77 //freopen("input.txt","r",stdin); 78 while(~scanf("%d%d%d%d",&n,&p,&src,&dst)) 79 { 80 for(int i=1;i<=n;i++) G[i].clear(); 81 memset(sw,0,sizeof(sw)); 82 83 for(int i=0;i<p;i++) 84 { 85 int a,b; ll c; 86 scanf("%d%d%lld",&a,&b,&c); 87 G[a].push_back(make_pair(b,c)); 88 G[b].push_back(make_pair(a,c)); 89 } 90 91 scanf("%d",&m); 92 for(int i=0;i<m;i++) 93 { 94 int x; 95 scanf("%d",&x); 96 sw[x]=1; 97 } 98 99 ll ans=0; 100 ll L=0,R=20000000000000LL; 101 while(L<=R) 102 { 103 ll mid=(L+R)/2; 104 if(dijkstra(mid)) 105 { 106 ans=mid; 107 L=mid+1; 108 } 109 else R=mid-1; 110 } 111 112 113 if(ans==0) puts("Impossible"); 114 else if(ans==20000000000000LL) puts("Infinity"); 115 else printf("%lld\n",ans); 116 } 117 return 0; 118 }
以上是关于LA 6891 Money Transfers(最短路)的主要内容,如果未能解决你的问题,请参考以下文章
Codeforces Round #353 (Div. 2) C. Money Transfers
CodeForces 675C Money Transfers(贪心+奥义维护)
Codeforces Round #353 (Div. 2) C. Money Transfers (思维)