http://poj.org/problem?id=3228
若干个城镇之间有若干条边相连,每个城镇存在一定容量的金矿或者仓库,或者两者都有或都没有,现在要把所有的金矿运到仓库里,求这样做要使用的最长边长度的最小值
一眼网络流(括弧笑)
实际上就是每个点存在一个权值:仓库容量-金矿容量,我们目标就是要连接若干条边使得每一个联通块总权值>=0,这个东西可以动态加边+并查集很好做,而且效率比网络流不知道好到哪里去了
#include<cstdio>
#include<algorithm>
using namespace std;
int n,sum,x,m;
int a[205],fa[205];;
struct edge{
int x,y,l;
}e[40005];
bool cmp(edge k1,edge k2){return k1.l<k2.l;}
int find(int k){
if(fa[k]==k)return k;
fa[k]=find(fa[k]);
return fa[k];
}
int main(){
while(scanf("%d",&n),n){
sum=0;
for(int i=1;i<=n;i++)scanf("%d",&a[i]);
for(int i=1;i<=n;i++){
scanf("%d",&x);
a[i]-=x;
fa[i]=i;
if(a[i]>0)sum++;
}
scanf("%d",&m);
for(int i=1;i<=m;i++)scanf("%d%d%d",&e[i].x,&e[i].y,&e[i].l);
sort(e+1,e+1+m,cmp);
int i;
for(i=1;i<=m;i++){
int X=find(e[i].x),Y=find(e[i].y);
if(X!=Y){
if(a[X]>0)sum--;
if(a[Y]>0)sum--;
a[X]+=a[Y];
fa[Y]=X;
if(a[X]>0)sum++;
}
if(sum==0)break;
}
if(sum==0)printf("%d\n",e[i].l);
else printf("No Solution\n");
}
}
评论 (0)