uva11478(差分约束,spfa求负环)
UVA - 11478 Halum (最短路应用+二分)
Description
Problem H
|
Halum
|
Time Limit : 3 seconds
|
||
As an example of that operation, consider graph G that has three vertices named (1, 2, 3) and two edges. Edge (1, 2) has cost -1, and edge (2,3) has cost 1. The operation Halum(2,-3) operates on edges entering and leaving vertex 2. Thus, edge (1, 2) gets cost -1-(-3)=2 and the edge (2, 3) gets cost 1 + (-3) = -2. Your goal is to apply the Halum function to a graph, potentially repeatedly, until every edge in the graph has at least a certain cost that is greater than zero. You have to maximize this cost.
|
||||
Input | ||||
Two space-separated integers per case: V(V≤500) and E(E≤2700). E lines follow. Each line represents a directed edge using three space-separated integers (u, v, d). Absolute value of cost can be at most 10000. |
||||
Output | ||||
If the problem is solvable, then print the maximum possible value. If there is no such solution print “No Solution”. If the value can be arbitrary large print “Infinite” |
||||
Sample Input | Sample Output | |||
2 1
|
Infinite |
题意:给定一个有向图,每条边都有一个权值,每次你可选择一个结点v和一个整数d,把所有以v为终点的边的权值减少d,把所有以v为终点的边的权值增加d,最后要让所有边的最小值非负且尽量大。
思路:最小值最大,大牛们想到用二分求答案,令sum(u)表示为作用在节点u之上的所有d之和,这样题目的目标就是确定所有的sum(u)了; 对于边a->b,不难发现操作后的权值是:w(a, b)+sum(a)-sum(b)>=x
那么就可以得到个不等式:sum(b)-sum(a) <= w(a, b)-x,而w(a, b)-x我们是已知的,那么就能得到相当于最短路的
不等式 d[v]<=d[u]+w(u, v),这样,我们实际得到一个差分约束系统。,那么我们在做spfa的时候,如果发现负权环的话,那么就相当于我们无法得到一个类似最短路的不等式,所以无解。
#include <iostream> #include <stdio.h> #include <stdlib.h> #include<string.h> #include<algorithm> #include<math.h> #include<queue> using namespace std; const int N=505; typedef long long ll; int dis[N]; int cnt[N],m,n; bool vis[N]; int head[N]; int ip; struct edgenode { int to,w; int next; } tu[N*N]; void add(int u,int v,int w) { tu[ip].to=v,tu[ip].w=w,tu[ip].next=head[u],head[u]=ip++; } bool spfa() { queue<int>q; for(int i=1; i<=n; i++) dis[i]=0,cnt[i]=0,vis[i]=0,q.push(i); while(!q.empty()) { int t=q.front(); q.pop(); vis[t]=0; for(int k=head[t]; k!=-1; k=tu[k].next) if(dis[t]+tu[k].w<dis[tu[k].to]) { dis[tu[k].to]=dis[t]+tu[k].w; if(!vis[tu[k].to]) { vis[tu[k].to]=1; q.push(tu[k].to); if(++cnt[tu[k].to]>=n) return 0; } } } return 1; } bool judge(double x) { bool flag=0; for(int i=1; i<=n; i++) for(int k=head[i]; k!=-1; k=tu[k].next) tu[k].w-=x; if(!spfa())flag=1; for(int i=1; i<=n; i++) for(int k=head[i]; k!=-1; k=tu[k].next) tu[k].w+=x; return flag; } int main() { while(~scanf("%d%d",&n,&m)) { ip=0; memset(head,-1,sizeof(head)); int l=1,r=0,mid; while(m--) { int a,b,w; scanf("%d%d%d",&a,&b,&w); add(a,b,w); r=max(r,w); } if(!judge(r)) printf("Infinite\n"); else if(judge(l)) printf("No Solution\n"); else { int ans=l++; while(l<r) { mid=(r+l)/2; if(judge(mid)) r=mid; else l=mid+1,ans=mid; } printf("%d\n",ans); } } return 0; }