原题: http://poj.org/problem?id=3228
题意:
有n个点,m条边,每个点有一个存储量和货物量,求运输的最长路段(路径中最长的那条)的最小值,使所有货物可以存放。
解析:
首先二分答案,小于等于答案的边直接连上,流量设inf
然后源点到各个点,流量设为货物量
所有点到汇点,流量设为存储量
#include<stdio.h>
#include<iostream>
#include<math.h>
#include<algorithm>
#include<string.h>
#include<queue>
using namespace std;
const int inf=0x3f3f3f3f;
const int N=1001,M=100001;
int head[N],nex[M],to[M],val[M],now;
void add(int a,int b,int v){
to[++now]=b;val[now]=v;nex[now]=head[a];head[a]=now;
to[++now]=a;val[now]=0;nex[now]=head[b];head[b]=now;
}
//*********************
int sp,ep,d[N];
int bfs(){
queue<int>Q;
memset(d,-1,sizeof(d));
d[sp]=0;
Q.push(sp);
while(!Q.empty()){
int p=Q.front();Q.pop();
for(int i=head[p];~i;i=nex[i]){
int u=to[i];
if(d[u]==-1&&val[i]>0){
d[u]=d[p]+1;
Q.push(u);
}
}
}
return d[ep]!=-1;
}
int dfs(int p,int v){
int r=0;
if(p==ep)return v;
for(int i=head[p];(~i)&&r<v;i=nex[i]){
int u=to[i];
if(val[i]>0&&d[u]==d[p]+1){
int x=dfs(u,min(val[i],v-r));
r+=x;
val[i]-=x;
val[i^1]+=x;
}
}
if(!r)d[p]=-2;
return r;
}
int dinic(){
int ans=0,t;
while(bfs()){
while(t=dfs(sp,inf))ans+=t;
}
return ans;
}
//***********************
void init(){
now=-1;//要求第一条边为0
memset(head,-1,sizeof(head));
}
int n,m,sum;
int a[M],b[M],v[M];
int s[N],g[N];
int judge(int limit){
init();
sp=0,ep=201;
for(int i=1;i<=m;i++){
if(v[i]<=limit){
add(a[i],b[i],inf);
add(b[i],a[i],inf);
}
}
for(int i=1;i<=n;i++){
if(s[i]){
add(0,i,s[i]);
}
if(g[i]){
add(i,201,g[i]);
}
}
int ans=dinic();
if(ans==sum)return 1;
return 0;
}
int main(){while(scanf("%d",&n)!=EOF){
if(!n)break;
sum=0;
for(int i=1;i<=n;i++)scanf("%d",s+i),sum+=s[i];
for(int i=1;i<=n;i++)scanf("%d",g+i);
scanf("%d",&m);
int l=0,r=1e4;
for(int i=1;i<=m;i++)scanf("%d%d%d",a+i,b+i,v+i);
if(!judge(1e4)){printf("No Solution\n");continue;}
if(judge(0)){printf("%d\n",0);continue;}
while(r-l>1){
int mid=l+r>>1;
if(judge(mid))r=mid;
else l=mid;
}
printf("%d\n",r);
}}