• POJ 3228 [并查集]


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

    题意:给出n个村庄,每个村庄有金矿和仓库,然后给出m条边连接着这个村子。问题是把所有的金矿都移动到仓库里所要经过的路径的最大值的最小值。

    题解:贪心,把边排序,然后从小到大加边,如果加到某一条边之后,金矿都可以移动到仓库了,那么这条边就是结果。首先明白,如果一些边连接的一些村庄的仓库的总容量大于总金矿数,那么这些村庄的金矿就可以全部移动到仓库里了。如果在从小到大加边的时候形成了环,那么这条边可以不要(加进去也不会影响结果),然后用并查集维护就可以了,注意:在用并查集维护的时候,记得把仓库和金矿都移动到根节点,这样便于判断是否已经满足了情况了。

    //#include<bits/stdc++.h>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    typedef long long LL;
    using namespace std;
    const int maxn = 250;
    struct node
    {
        int st, ed, dis;
        bool operator < (const node T) const
        {
            return dis < T.dis;
        }
    } E[maxn * maxn];
    int g[maxn], h[maxn], N, M;
    int f[maxn];
    int Find(int u)
    {
        if(u == f[u]) return f[u];
        else return f[u] = Find(f[u]);
    }
    void adde(int u, int v)
    {
        f[u] = v;
        h[v] += h[u];
        h[u] = 0;
        g[v] += g[u];
        g[u] = 0;
    }
    bool check()
    {
        for(int i = 1; i <= N; i++)
        {
            int u = Find(i);
            if(h[u] < g[u]) return false;
        }
        return true;
    }
    int main ()
    {
        while(~scanf("%d", &N), N)
        {
            for(int i = 1; i <= N; i++)
                f[i] = i;
            int sumg = 0, sumh = 0;
            for(int i = 1; i <= N; i++)
            {
                scanf("%d", &g[i]);
                sumg += g[i];
            }
            for(int i = 1; i <= N; i++)
            {
                scanf("%d", &h[i]);
                sumh += h[i];
            }
            if(sumh < sumg)
            {
                printf("No Solution
    ");
                continue;
            }
            scanf("%d", &M);
            for(int i = 1; i <= M; i++)
                scanf("%d%d%d", &E[i].st, &E[i].ed, &E[i].dis);
            sort(E + 1, E + 1 + M);
            int ans = 0;
            if(check())
            {
                printf("%d
    ", ans);
                continue;
            }
            for(int i = 1; i <= M; i++)
            {
                int u = Find(E[i].st);
                int v = Find(E[i].ed);
                if(u == v) continue;
                adde(u, v);
                ans = E[i].dis;
                if(check()) break;
            }
            if(check()) printf("%d
    ", ans);
            else printf("No Solution
    ");
        }
        return 0;
    }
    想的太多,做的太少。
  • 相关阅读:
    设计模式-策略模式
    java8 流式编程
    《JAVA8开发指南》使用流式操作
    linux如何查看端口被哪个进程占用?
    mac 启动php-fpm报错 failed to open configuration file '/private/etc/php-fpm.conf': No such file or direc
    Mac home 目录下创建文件夹
    UML由浅入深
    PHP扩展Swoole的代码重载机制
    Gedit中文乱码
    linux 内核源码arch/ 目录的前世今生
  • 原文地址:https://www.cnblogs.com/pealicx/p/6707487.html
Copyright © 2020-2023  润新知