zoukankan      html  css  js  c++  java
  • 【CodeVS3372】选学霸

    Description

    老师想从N名学生中选M人当学霸,但有K对人实力相当,如果实力相当的人中,一部分被选上,另一部分没有,同学们就会抗议。所以老师想请你帮他求出他该选多少学霸,才能既不让同学们抗议,又与原来的M尽可能接近。

    Input

    第一行,三个正整数N,M,K。

    第2...K行,每行2个数,表示一对实力相当的人的编号(编号为1…N)。

    Output

    一行,表示既不让同学们抗议,又与原来的M尽可能接近的选出学霸的数目。(如果有两种方案与M的差的绝对值相等,选较小的一种。)

    Sample Input

    4 3 2

    1 2

    3 4

    Sample Output

    2

    HINT

    100%的数据N,P<=30000

    题解

    先并查集,把实力相同的人合并,然后01背包(v是2倍,因为是绝对值之差最小),找出最接近的装满的取差比较大小。

    注意 并查集完成以后要

        for (int i=1;i<=n;i++) f[i]=root(i);

    举个例子

    f 1 2 3 4 5 6

    (1 3) 1 2 1 4 5 6

    (5 6) 1 2 1 4 5 5 

    (1 5) 1 2 1 4 1 5 (f[6]还是5)

    (小醇发现的!小醇实在是太机智了!)

    #include<iostream>
    #include<cstdio>
    using namespace std;
    int f[30010],d[30010],v[30010],a[60010];
    int n,m,k,cnt,x,y;
    
    int root (int x){
        if (f[x]!=x) f[x]=root(f[x]); return f[x];
    }
    int main(){
        scanf("%d%d%d",&n,&m,&k);
        for (int i=1;i<=n;i++) f[i]=i;
        for (int i=1;i<=k;i++){
            scanf("%d%d",&x,&y);if (root(x)!=root(y)) f[f[x]]=f[y];
        }
        for (int i=1;i<=n;i++) f[i]=root(i);
        for (int i=1;i<=n;i++) d[f[i]]++;
        for (int i=1;i<=n;i++){
            if(d[i]){
                v[++cnt]=d[i];
            }
        }
        n=cnt;
        for (int i=1;i<=n;i++)
            for (int j=2*m;j>=v[i];j--)
            a[j]=max(a[j],a[j-v[i]]+v[i]);
        int i;
        for (i=m+1;i<=2*m;i++) if (a[i]==i) break;
        if (min(m-a[m],i-m)==m-a[m]) cout<<a[m];else cout<<i;
    }
  • 相关阅读:
    软件测试——一点看法
    软件测试——注意事项
    软件测试——Peer Review
    软件测试——白盒测试
    软件测试——闰年检测程序及异常问题解决
    JS动态,有选择性的改变div颜色
    软件测试——EditBox等价类划分扩展
    软件测试——EditBox等价类划分
    初窥软件测试
    开博第一篇
  • 原文地址:https://www.cnblogs.com/liumengyue/p/5271895.html
Copyright © 2011-2022 走看看