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 (思维)

UVA1258 LA4721 Nowhere Money数学计算

Laravel 多用户 id 表

Java NIO Channel to Channel Transfers