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;
}
发布了42 篇原创文章 · 获赞 29 · 访问量 7626

猜你喜欢

转载自blog.csdn.net/qq_44077455/article/details/104152843