HDU 5438 Ponds(拓扑排序+dfs)

Description
给出一张n个点m条边的无向图,每个点有一个点权,删掉所有度数小于等于2的点之后,问点数为奇数的连通块中点权之和
Input
第一行一整数T表示用例组数,每组用例首先输入两个整数n和m表示点数和边数,然后输入n个整数vi表示每个点的点权,最后m行每行两个整数u和v表示u和v之间有一条边(1<=T<=30,1<=n<=10^4,1<=m<=10^5)
Output
对于每组用例,输出删完点后点数为奇数的连通块中点权之和
Sample Input
1
7 7
1 2 3 4 5 6 7
1 4
1 5
4 5
2 3
2 6
3 6
2 7
Sample Output
21
Solution
先按拓扑排序的思想删点,删完点后重新建图,然后dfs找连通块,点数为奇的就将点权累加到结果中
Code

#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<vector>
#include<queue>
using namespace std;
typedef long long ll;
#define maxn 11111
int T,n,m,res,cnt,vis[maxn],w[maxn];
vector<int>G[maxn],g[maxn];
ll sum;
void dfs(int u)
{
    vis[u]=res,cnt++,sum+=w[u];
    for(int i=0;i<g[u].size();i++)
    {
        int v=g[u][i];
        if(vis[v])continue;
        dfs(v);
    }
}
queue<int>q;
int d[maxn],used[maxn];
void deal(int n)
{
    while(!q.empty()) q.pop();
    memset(used,0,sizeof(used));
    for(int i=1;i<=n;i++)
    {
        d[i]=G[i].size();
        if(d[i]<2)q.push(i);
    }
    while(!q.empty())
    {
        int u=q.front();
        q.pop();
        used[u]=1;
        for(int i=0;i<G[u].size();i++)
        {
            int v=G[u][i];
            if(!used[v])
            {
                d[v]--;
                if(d[v]<2)q.push(v);
            }
        }
    }
}
int main()
{
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++)scanf("%d",&w[i]),G[i].clear(),g[i].clear();
        while(m--)
        {
            int u,v;
            scanf("%d%d",&u,&v);
            G[u].push_back(v),G[v].push_back(u);
        }
        deal(n);
        for(int i=1;i<=n;i++)
            if(!used[i])
                for(int j=0;j<G[i].size();j++)
                {
                    int k=G[i][j];
                    if(used[k])continue;
                    g[i].push_back(k);
                }
        memset(vis,0,sizeof(vis));
        ll ans=0;
        res=0;
        for(int i=1;i<=n;i++)
        {
            res++,cnt=0;sum=0;
            if(!vis[i]&&!used[i])dfs(i);
            if(cnt&1)ans+=sum;
        }
        printf("%I64d\n",ans);
    }
    return 0;
}
    原文作者:拓扑排序
    原文地址: https://blog.csdn.net/V5ZSQ/article/details/52311182
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞