例题5.16 Halum操作 UVa11478
来源:互联网 发布:仿手写软件app 编辑:程序博客网 时间:2024/06/09 14:28
1.题目描述:点击打开链接
2.解题思路:本题利用BellmanFord算法+二分解决。本题要求执行完一系列Halum操作后,可以让边权的最小值非负且尽量大。自然想到可以用二分法来解决。假设答案是x。即问题转化为所有边的边权经过操作后都大于等于x。然而这里有一个问题,我们根本不知道应该怎么选取相应的v,d,使得可以达到这个目标。但是仔细观察后就可以注意到一个特点:不同的操作影响是相互独立的,即影响是符合叠加原理的。假设我们对u结点执行了d1,d2..dk种操作,可以等价为只执行了d1+d2+..+dk这一种操作。这样,我们可以考虑把每个结点i等效的操作数设置为Xi,那么对于每一条边A->B,有w(A,B)+X(A)-X(B)>=x,移项后得到X(B)-X(A)<=w(A,B)-x。这样,我们实际上得到了m个不等式组。这个不等式组构成了一个“差分约束系统”。如果这个不等式组有解,那么x值就是可以得到的,否则就是不可能得到的。那么现在问题转化为如何判断解是否存在。
考虑到最短路中的不等式d[v]<=d[u]+w[u,v],我们可以用最短路来判断,把0结点处的X(0)设置为0,如果有X(B)-X(A)<=w(A,B)-x,就连一条A->B的边,边权恰好是w(A,B)-x。这样就和最短路的不等式完全一样了。可以直接用Dijkstra算法求解了。但是我们没有必要真的求出来每个点的具体值,而只是判断解是否存在。最短路不存在的条件当且仅当图中存在负圈。那么就可以用BellmanFord算法来判断解的存在性了。至此,问题得以解决。
3.代码:
#include<iostream>#include<algorithm>#include<cassert>#include<string>#include<sstream>#include<set>#include<bitset>#include<vector>#include<stack>#include<map>#include<queue>#include<deque>#include<cstdlib>#include<cstdio>#include<cstring>#include<cmath>#include<ctime>#include<cctype>#include<list>#include<complex>#include<functional>using namespace std;#define me(s) memset(s,0,sizeof(s))#define rep(i,n) for(int i=0;i<(n);i++)#define pb push_backtypedef long long ll;typedef unsigned int uint;typedef unsigned long long ull;typedef pair <int,int> P;const int INF=1e9;const int maxn=500+10;const int maxm=2700+10;struct Edge{int to,dist;};struct BellmanFord{ int n,m; Edge edges[maxm]; int head[maxn]; int next[maxm]; bool inq[maxn]; int d[maxn],cnt[maxn]; void init(int n) { this->n=n; m=0; memset(head,-1,sizeof(head)); } void addedge(int u,int v,int dist) { edges[m]=Edge{v,dist}; next[m]=head[u]; head[u]=m++; } bool negativeCycle() { queue<int>q; memset(inq,0,sizeof(inq)); memset(cnt,0,sizeof(cnt)); for(int i=0;i<n;i++){d[i]=0;q.push(i);} while(!q.empty()) { int u=q.front();q.pop(); inq[u]=false; for(int i=head[u];~i;i=next[i]) { Edge&e=edges[i]; if(d[e.to]>d[u]+e.dist) { d[e.to]=d[u]+e.dist; if(!inq[e.to]) { q.push(e.to);inq[e.to]=true; if(++cnt[e.to]>n)return true; } } } } return false; }};BellmanFord solver;bool test(int x)//判断边权的最小值是否可以为x,等价于判断所有边权都减掉x后,整个图是否存在负圈{ for(int i=0;i<solver.m;i++) solver.edges[i].dist-=x; bool ret=solver.negativeCycle(); for(int i=0;i<solver.m;i++) solver.edges[i].dist+=x; return !ret;}int main(){ int n,m; while(~scanf("%d%d",&n,&m)) { solver.init(n); int ub=0; while(m--) { int u,v,d; scanf("%d%d%d",&u,&v,&d); ub=max(ub,d); solver.addedge(u-1,v-1,d); } if(test(ub+1))puts("Infinite"); //如果最小值可以达到最大值+1,说明是可以无限大的,因为如果反复执行相同的操作,就会让边权继续增大,趋于无限 else if(!test(1))puts("No Solution");//如果最小值连1都达不到,说明无解 else { int L=2,R=ub,ans=1; while(L<=R) { int M=L+(R-L)/2; if(test(M)){ans=M;L=M+1;} else R=M-1; } printf("%d\n",ans); } }}
0 0
- 例题5.16 Halum操作 UVa11478
- UVA11478 Halum
- uva11478 Halum
- uva11478 - Halum
- UVa11478 - Halum
- UVA11478 Halum (差分约束)
- UVa11478 - Halum(差分约束)
- uva11478 - Halum 二分+差分约束
- uva11478 Halum【二分+差分约束】
- UVA11478-Halum(BellmanFord + 差分约束)
- UVA11478 [Halum] 二分答案+SPFA差分约束系统
- uva11478
- UVA11478 Halum 解题报告【图论】【二分答案】【SPFA】【差分约束系统】
- 差分约束(Halum操作,UVA 11478)
- UVA11478 二分
- PV操作例题
- PV操作例题解析
- Oracle数据库操作例题
- ocp-55
- python requests库官方手册
- ocp-56
- ocp-57
- Linux下paste命令详解
- 例题5.16 Halum操作 UVa11478
- ocp-58
- 并发访问数据可能存在的问题
- 关于LDR链接器脚本所产生的2B错误
- golang snmp开发学习笔记(一)
- java 网络编程——day23
- ocp-59
- 连续子串最大最小异或值 Trie+Xor LightOJ 1269 Consecutive Sum
- ocp-60