首页 > 代码库 > LA 6891 Money Transfers(最短路)

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(最短路)