zoukankan      html  css  js  c++  java
  • HDU

    题目:

    给出一个无向图,将图中度数小于等于1的点删掉,并删掉与他相连的点,直到不能在删为止,然后判断图中的各个连通分量,如果这个连通分量里边的点的个数是奇数,就把这些点的权值求和。

    思路:

    先用拓扑排序删点并更新各个点的度数,然后用并查集判断各个连通分量里边的点个数的奇偶性就ok了。

    代码:

    #include <bits/stdc++.h>
    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <vector>
    #include <algorithm>
    #include <queue>
    #include <iomanip>
    #define MAX 1000000000
    #define inf 0x3f3f3f3f
    #define FRE() freopen("in.txt","r",stdin)
    
    using namespace std;
    typedef long long ll;
    const int maxn = 10005;
    int degree[maxn],fa[maxn],cnt[maxn],vis[maxn];
    int p,m;
    ll val[maxn],sum[maxn];
    vector<int> mp[maxn];
    
    void init()
    {
        memset(cnt,0,sizeof(cnt));
        memset(degree,0,sizeof(degree));
        memset(sum,0,sizeof(sum));
        memset(vis,0,sizeof(vis));
        for(int i=0; i<maxn; i++)
        {
            fa[i] = i;
            mp[i].clear();
        }
    }
    
    int _find(int x)
    {
        return fa[x]==x?x:fa[x] = _find(fa[x]);
    }
    
    
    void check()
    {
        for(int i=1; i<=p; i++)
        {
            printf("%d ",degree[i]);
        }
        printf("
    ");
    }
    
    int main()
    {
        //FRE();
        int kase;
        scanf("%d",&kase);
        while(kase--)
        {
            init();
            scanf("%d%d",&p,&m);
            for(int i=1; i<=p; i++)
            {
                scanf("%lld",&val[i]);
            }
            for(int i=0; i<m; i++)
            {
                int u,v;
                scanf("%d%d",&u,&v);
                degree[u]++;
                degree[v]++;
                mp[u].push_back(v);
                mp[v].push_back(u);
                u = _find(u);//将同一个连通分量里边的点连接
                v = _find(v);
                if(u!=v)
                    fa[u] = v;
            }
            //check();
            queue<int> que;
            for(int i=1; i<=p; i++)
            {
                if(degree[i]<=1)
                    que.push(i);
            }
            while(!que.empty())//利用拓扑排序删点
            {
    
                int u = que.front(); que.pop();
                //cout<<u<<endl;
                vis[u] = 1;
                for(int i=0; i<mp[u].size(); i++)
                {
                    degree[mp[u][i]]--;
                    if(!vis[mp[u][i]] && degree[mp[u][i]]<=1)
                        que.push(mp[u][i]);
                }
            }
            //check();
            ll ans = 0;
            for(int i=1; i<=p; i++)
            {
                if(degree[i]<=1) continue;
                int r = _find(i);
                cnt[r]++;//统计该连通分量里边的点的个数
                sum[r] += val[i];//该连通分量的权值的和
            }
            for(int i=1; i<=p; i++)
            {
                if(cnt[i]%2)
                {
                    ans += sum[i];
                }
            }
            printf("%lld
    ",ans);
        }
        return 0;
    }
  • 相关阅读:
    dotnetcharting 生成柱状图,饼图等统计图
    asp.net 前后台相互调用
    SQL基础和高级(语法格式)总结二
    自己动手JQuery插件开发
    SQL基础之创建数据库,表,架构
    SQL基础和高级(语法格式)总结一
    ado.net总结
    [Nescafé 26] 小猫爬山&&售货员的难题&&区间众数(随机化大法好)
    POJ2774 后缀自动机&后缀数组
    【方向学习】单片机
  • 原文地址:https://www.cnblogs.com/sykline/p/10538423.html
Copyright © 2011-2022 走看看