poj3228(並查集)

題目一開始題都沒讀懂,“maximum adjacent distance”把我給整懵了。。。
題意:給一個圖,圖中一些點有黃金,一些點有放黃金的倉庫,但有容量限制,問把所有黃金都能裝進倉庫的路徑中權值最大的那條路是多少。
思路:這道題可以用並查集,先記錄輸出黃金的城市個數num,並用sum[i]表示第i個點是輸出黃金還是輸入黃金,把黃金所有量或者倉庫存儲量都給並查集的頭,在合併的時候,出現了輸出城市減少的情況,則num-1,直到num=0,num不能爲0則是不可能。開始以爲只有一輛車來運,想着合成一個集合就可以,但是後來發現可以多輛車同時搞,也就是完成任務時可能有多個集合,所以採用記錄輸出黃金城市個數的方式。

//對於輸出城市減少的情況討論:
//合併時無非只有以下四種情況,分別對應的結果如下
/*******************************/
//結點       父親      兒子               結果
//sum值      >0(輸出)  <0(輸入)          當sum[父親] + sum[兒子] <= 0的時候  num-- (少了父親這個城市)
//sum值      <0(輸入)  >0(輸出)          當sum[父親] + sum[兒子] <= 0的時候  num-- (少了兒子0這個城市)
//sum值      >0(輸出)  >0(輸出)          num-- (少了兒子這個城市)
//sum值      <0(輸入)  <0(輸入)          num不變
/*******************************/
//#include<bits/stdc++.h>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#define mod (10007)
#define middle (l+r)>>1
#define SIZE 1000000+5
#define lowbit(x) (x&(-x))
#define lson (rt<<1)
#define rson (rt<<1|1)
typedef long long ll;
typedef long double ld;
const int inf_max = 0x3f3f3f;
const ll Linf = 9e18;
const int maxn = 200 + 10;
const long double E = 2.7182818;
const double eps=0.0001;
using namespace std;
inline int read()
{
    int f=1,res=0;
    char ch=getchar();
    while(ch<'0'||ch>'9') { if(ch=='-') f=-1; ch=getchar(); }
    while(ch>='0'&&ch<='9') { res=res*10+ch-'0' ; ch=getchar(); }
    return f*res;
}
struct EDG {
    int v,u,val;
    bool operator<(const EDG &a)const {
        return val < a.val;
    }
}edge[maxn*maxn];
int n,m,tot,fa[maxn],cnt,ans,sum[maxn],num;//// sum[i]爲正代表還有黃金輸出
void Initial() {
    for(int i = 1;i <= n; ++i) fa[i] = i;
    memset(edge,0,sizeof(edge));
    memset(sum,0,sizeof(sum));
    cnt = ans = num = 0;
}
void add_edge(int u,int v,int val) {
    edge[cnt].val = val;
    edge[cnt].v = v;
    edge[cnt++].u = u;
}
int Find(int x) {
    if(fa[x] == x) return fa[x];
    return fa[x] = Find(fa[x]);
}
int main()
{
    while(scanf("%d",&n),n) {
        Initial();
        for(int i = 1;i <= n; ++i) {
            int tt = read();
            sum[i] += tt;
        }
        for(int i = 1;i <= n; ++i) {
            int tt = read();
            sum[i] -= tt;
            if(sum[i] > 0) num++;
        }
        m = read();
        for(int i = 1;i <= m; ++i) {
            scanf("%d%d%d",&edge[i].u,&edge[i].v,&edge[i].val);
        }
        sort(edge + 1,edge + 1 + m);
        for(int i = 1;i < m; ++i) {
            int u = edge[i].u,v = edge[i].v,val = edge[i].val;
            int fu = Find(u),fv = Find(v);
            if(fu != fv) {
                int minf = min(fu,fv),maxf = max(fu,fv),cur = sum[minf] + sum[maxf];
                fa[maxf] = minf;
                if(sum[maxf] > 0 && sum[minf] > 0) num--;
                else if(sum[minf] * sum[maxf] < 0 && cur <= 0) num--;
                sum[minf] = cur;
                if(num == 0) {
                    printf("%d\n",val);
                    break;
                }
            }
        }
        if(num) printf("No Solution\n");
    }
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章