• 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;
    }
  • 相关阅读:
    9-python 的ProxyHandler处理器(代理设置)
    2018.2.7 css 的一些方法盒子模型
    2018.2.6 JS-判断用户浏览器
    2018.2.5 PHP如何写好一个程序用框架
    2018. 2.4 Java中集合嵌套集合的练习
    2018.2.3 Centos 的vim好看的主题配置及JDK的安装配置
    2018.2.2 java中的Date如何获取 年月日时分秒
    2018.2.2 JavaScript中的封装
    2018.1.30 PHP编程之验证码
    2018.1.29 计算机二级错题汇总(二)
  • 原文地址:https://www.cnblogs.com/sykline/p/10538423.html
Copyright © 2020-2023  润新知