zoukankan      html  css  js  c++  java
  • HDU-6380 degree(图论&并查集)

    Problem Description
    度度熊最近似乎在研究图论。给定一个有 N 个点 (vertex) 以及 M 条边 (edge) 的无向简单图 (undirected simple graph),此图中保证没有任何圈 (cycle) 存在。

    现在你可以对此图依序进行以下的操作:

    1. 移除至多 K 条边。
    2. 在保持此图是没有圈的无向简单图的条件下,自由的添加边至此图中。

    请问最后此图中度数 (degree) 最大的点的度数可以多大呢?

    Input
    输入的第一行有一个正整数 T,代表接下来有几笔测试资料。

    对于每笔测试资料:
    第一行有三个整数 N, M, K。
    接下来的 M 行每行有两个整数 a 及 b,代表点 a 及 b 之间有一条边。
    点的编号由 0 开始至 N−1。

    • 0≤K≤M≤2×105
    • 1≤N≤2×105
    • 0≤a,b < N
    • 给定的图保证是没有圈的简单图
    • 1≤T≤23
    • 至多 2 笔测试资料中的 N>1000

    Output
    对于每一笔测试资料,请依序各自在一行内输出一个整数,代表按照规定操作后可能出现的最大度数。

    Sample Input
    2
    3 1 1
    1 2
    8 6 0
    1 2
    3 1
    5 6
    4 1
    6 4
    7 0

    Sample Output
    2
    4

    煞笔题目一开始思路错了,以为给出的k任意选就是最大度数,然而并不是这样的。一定删掉的k条边不是度数最多的那个点的边,否则k就浪费了。

    所以首先分类讨论,对于k大于m时,一定能把所有边删掉,那么最优情况把大家都连到一个点上即可,即答案为n-1

    另一种情况,为了防止加边而出现环,只能对不是一棵树上的点加边,记录所有节点的度数,用并查集将没有联通的树分开,选择度数最多的一个点不动,记录树的个数,也就是这些树与度数最多的点加边不会出现环,用总边数减去度数最多的点的度数,也就是直连度数最多点的边,剩余的边时可以被删除的,那么如果K大于剩余边数,直接是最优答案n-1,否则,我们删一条边就可以独立出一个点连到度数最多的点上,所以最终答案是 度数最大值-独立树的个数-1【度数最大值本身所在的树】+k【删除一条边多一个度数】

    #include<bits/stdc++.h>
    #define LL long long
    using namespace std;
    const int maxn=2e5+10;
    int t,n,m,k;
    int cnt[maxn],z[maxn];
    int finds(int x)
    {
        return z[x]==x?x:z[x]=finds(z[x]);
    }
    void join(int a,int b)
    {
        int fa=finds(a),fb=finds(b);
        if(fa!=fb)z[fa]=fb;
    }
    int main()
    {
        scanf("%d",&t);
        while(t--)
        {
            LL a,b,ans=0;
            memset(cnt,0,sizeof cnt);
            scanf("%d%d%d",&n,&m,&k);
            for(int i=1; i<=m; i++)
            {
                scanf("%I64d%I64d",&a,&b);
                cnt[a]++;
                cnt[b]++;
                join(a,b);
            }
            if(k>=m)
            {
                printf("%d
    ",n-1);
                continue;
            }
            int mx=0;
            for(int i=0; i<n; i++)
            {
                if(cnt[i]>mx)mx=cnt[i];
                if(z[i]==i)ans++;
            }
            if(k>=m-mx)
            {
                printf("%I64d
    ",n-1);
                continue;
            }
            else ans+=mx+k-1;
            printf("%I64d
    ",ans);
        }
    }
    
  • 相关阅读:
    前端- css
    前端- html -总结
    2016.9.15 黑客编程之无限启动
    2016.9.14 JavaScript入门之七面向对象和函数
    2016.9.13 JavaScript入门之六基础函数
    2016.9.1 JavaScript入门之五
    2016.9.9 网络工程师之路由器技术
    2016.8.14 网络工程师之网关协议
    2016.8.27 JavaScript入门之四
    2016.8.22 JavaScript入门之三
  • 原文地址:https://www.cnblogs.com/kuronekonano/p/11135718.html
Copyright © 2011-2022 走看看