题意:
有n和城市和m条路,每个城市都有产生金量和收集金量,现在要把所有黄金收集,求经过的最短边是多少。
分析:
二分+最大流或用并查集合并等价类。
//poj 3228
//sep9
#include <iostream>
#include <algorithm>
using namespace std;
const int maxN=256;
const int maxM=10024;
int p[maxN],sum[maxN];
struct Edge
{
int u,v,w;
}e[maxM];
int cmp(Edge a,Edge b)
{
return a.w<b.w;
}
int find(int u)
{
if(p[u]==u)
return u;
int x=find(p[u]);
sum[x]+=sum[u];
sum[u]=0;
return p[u]=x;;
}
int main()
{
int n,m,x;
while(scanf("%d",&n)==1&&n){
for(int i=1;i<=n;++i){
sum[i]=0;
p[i]=i;
}
for(int i=1;i<=n;++i){
scanf("%d",&x);
sum[i]-=x;
}
for(int i=1;i<=n;++i){
scanf("%d",&x);
sum[i]+=x;
}
scanf("%d",&m);
for(int i=0;i<m;++i)
scanf("%d%d%d",&e[i].u,&e[i].v,&e[i].w);
sort(e,e+m,cmp);
int ok=0,ans=-1;
for(int i=0;i<m;++i){
int u=e[i].u;
int v=e[i].v;
int pu=find(u);
int pv=find(v);
if(pu!=pv){
p[pu]=pv;
sum[pv]+=sum[pu];
sum[pu]=0;
}
int ok=1;
for(int j=1;j<=n;++j)
if(p[j]==j&&sum[j]<0){
ok=0;
break;
}
if(ok==1){
ans=i;
break;
}
}
if(ans==-1) puts("No Solution");
else printf("%d\n",e[ans].w);
}
return 0;
}