Ponds----hdu5438(拓扑排序)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5438

 

题意:有n个池塘和m个管道;每个池塘的价值是v, 现在由于资金问题要删除池塘;但是删除的池塘必须是最多只连接一个管道,否则会爆炸;

求最后相连的池塘有奇数个的价值总和是多少;

 

#include<iostream>
#include<stdio.h>
#include<string.h>
#include<vector>
#include<queue>
using namespace std;
#define N 100100
#define INF 0xfffffff

int v[N], f[N], du[N], vis[N], a[N], b[N], sum[N];
vector<vector<int> > G;

int Find(int x)
{
    if(x!=f[x])
        f[x] = Find(f[x]);
    return f[x];
}

int main()
{
    int T, n, m;
    scanf("%d", &T);
    while(T--)
    {
        scanf("%d%d", &n, &m);

        for(int i=1; i<=n; i++)
        {
            scanf("%d", &v[i]);
            f[i] = i;
            sum[i] = du[i] = vis[i] = 0;
        }
        G.resize(n+1);
        G.clear();
        for(int i=1; i<=m; i++)
        {
            scanf("%d%d", &a[i], &b[i]);

            du[a[i]]++;
            du[b[i]]++;
            G[a[i]].push_back(b[i]);
            G[b[i]].push_back(a[i]);
        }
        queue<int>Q;
        for(int i=1; i<=n; i++)
        {
            if(du[i]<2)///把度为<2的入队,并删除;
            {
                vis[i] = 1;
                Q.push(i);
            }
        }
        while(!Q.empty())
        {
            int p=Q.front();
            Q.pop();
            int len = G[p].size();
            for(int j=0; j<len; j++)
            {
                int q = G[p][j];
                du[q]--;
                if(vis[q]==0 && du[q]<2)
                {
                    Q.push(q);
                    vis[q] = 1;
                }
            }
        }
        
        for(int i=1; i<=m; i++)///让有联系的放到一个集合里
        {
            if(!vis[a[i]] && !vis[b[i]])
            {
                int pa = Find(a[i]);
                int pb = Find(b[i]);
                if(pa != pb)
                    f[pb] = pa;
            }
        }
        for(int i=1; i<=n; i++)
        {
            if(!vis[i])
                sum[Find(i)]++;///记录每个连通图的个数;
        }
        long long ans = 0;
        for(int i=1; i<=n; i++)
        {
            if(!vis[i] && sum[f[i]]%2==1)///判断是否有奇数个;
                ans+=v[i];
        }
        printf("%I64d\n", ans);
    }
    return 0;
}
View Code

 

posted @ 2015-09-15 20:23  西瓜不懂柠檬的酸  Views(320)  Comments(0Edit  收藏  举报
levels of contents