poj 3228 Gold Transportation 并查集

来源:互联网 发布:手机挂机软件 编辑:程序博客网 时间:2024/05/04 03:50

题目链接:http://poj.org/problem?id=3228

题目大意:有N座城市,每座城市都有a的金子和容量为b的仓库,有M条路,其中u,v,w表示从u到v的花费为w,现在问你把所有金子放进仓库的最小的最长路的长度。

解题思路:网上好多人用二分+网络流,鄙人不才,只能用并查集,首先把所有路径从小到大排列,然后依次添加路径,并记录金子的总运输量,当总运输量等于需要的运输量时,输出此时的路径,如果所有路径遍历完后不能把金子全运完,输出No Solution。

代码如下:

#include <cstdio>#include<iostream>#include <cstring>#include <cstdlib>#include<cmath>#include<algorithm>using namespace std;typedef double type;#define INF 2000000000#define N 205struct edge //图的结构体{    int u,v,w;}e[25005];int m,n,sum[N],f[N],SUM,gold,store;void init(){    SUM=0,gold=0,store=0;    for(int i=0;i<N;i++)        f[i]=i;    memset(sum,0,sizeof(sum));}int find(int x){    if(x!=f[x]) f[x]=find(f[x]);    return f[x];}bool merge(edge a){    bool flog=false;    int x=find(a.u);    int y=find(a.v);    if(x!=y)    {        f[x]=y;        if(sum[x]*sum[y]<0)        {            if(sum[x]+sum[y]>0)                gold-=min(sum[x],sum[y]);            else                gold+=max(sum[x],sum[y]);        }        sum[y]+=sum[x];        if(gold==SUM)            flog=true;    }    return flog;}bool cmp(edge a,edge b){    return a.w<b.w;}int main(){    while(~scanf("%d",&n)&&n)    {        int t;        init();        for(int i=1;i<=n;i++)        {            scanf("%d",&t);            sum[i]+=t;        }        for(int i=1;i<=n;i++)        {            scanf("%d",&t);            sum[i]-=t;        }        for(int i=1;i<=n;i++)            if(sum[i]>0) SUM+=sum[i];        scanf("%d",&m);        for(int i=1;i<=m;i++)            scanf("%d%d%d",&e[i].u,&e[i].v,&e[i].w);        sort(e+1,e+m+1,cmp);        int i;        for(i=1;i<=m;i++)        {            if(merge(e[i]))            {                printf("%d\n",e[i].w);                break;            }        }        if(i>m)            printf("No Solution\n");    }    return 0;}


 

0 0