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;
}