UVA11478 Halum
Posted zytwan
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了UVA11478 Halum相关的知识,希望对你有一定的参考价值。
看到求最小值最大,很容易联想到二分答案。
考虑二分答案后检验,因为对每一个点只能做一次有效操作(假设第一次加+d1,第二次+d2,可以简化成+(d1+d2))。因此考虑对每一个点的操作值重新建图。
设从i到j有一条初始权值为v的边,当前要验证的最小值为mid,每个点的操作值为x[i];很容易得到:v+x[i]-x[j]>=mid; 继而化简为x[j]-x[i]>=v-mid;
符合差分约束的模型。
于是从i到j建一条权值为v-mid的边,之后判负环即可。
1 #include<bits/stdc++.h> 2 using namespace std; 3 struct node{ 4 int to; 5 int v; 6 node(int a,int b) 7 { 8 to=a; 9 v=b; 10 } 11 }; 12 vector<node>v[605]; 13 int n,m,a[2705],b[2705],c[2705],d[605],vis[605],inque[605],flag; 14 void dfs(int x) 15 { 16 if(flag) return; 17 vis[x]=true; 18 inque[x]=true; 19 for(int i=0;i<v[x].size();i++) 20 { 21 int y=v[x][i].to; 22 if(d[y]>d[x]+v[x][i].v) 23 { 24 d[y]=d[x]+v[x][i].v; 25 if(inque[y]) 26 { 27 flag=1; 28 return; 29 } 30 else { 31 dfs(y); 32 } 33 } 34 } 35 inque[x]=false; 36 } 37 bool check(int x) 38 { 39 flag=0; 40 memset(vis,0,sizeof(vis)); 41 memset(inque,0,sizeof(inque)); 42 for(int i=1;i<=n;i++) 43 v[i].clear(); 44 for(int i=1;i<=m;i++) 45 v[a[i]].push_back(node(b[i],c[i]-x)); 46 memset(d,0x3f3f3f3f,sizeof(d)); 47 for(int i=1;i<=n;i++) 48 { 49 if(vis[i]) continue; 50 d[i]=0; 51 dfs(i); 52 } 53 if(flag) return false; 54 else return true; 55 } 56 57 int main() 58 { 59 while(cin>>n>>m) 60 { 61 for(int i=1;i<=m;i++) 62 { 63 cin>>a[i]>>b[i]>>c[i]; 64 } 65 int l=0,r=1e9; 66 while(l<r) 67 { 68 int mid=(l+r+1)/2; 69 if(check(mid)) l=mid; 70 else r=mid-1; 71 } 72 if(l==0) cout<<"No Solution"<<endl; 73 else if(l>=500000) cout<<"Infinite"<<endl; 74 else cout<<l<<endl; 75 } 76 77 }
以上是关于UVA11478 Halum的主要内容,如果未能解决你的问题,请参考以下文章