• 选学霸(codevs 3372)


    题目描述 Description

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

    输入描述 Input Description

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

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

    输出描述 Output Description

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

    样例输入 Sample Input

    4 3 2

    1 2

    3 4

    样例输出 Sample Output

    2

    数据范围及提示 Data Size & Hint

    100%的数据N,P<=30000

    /*
      由于实力相当的人不一定只有两个,所以先用并查集处理一下,统计每一组的人数,
      我们可以把每组同学看成一个物品,人数就是体积,这样就成了一个背包问题了。 
    */
    #include<cstdio>
    #include<cstdlib>
    #include<iostream>
    #define M 30010
    using namespace std;
    int fa[M],n,m,p;
    int v[M],belong[M],f[M],cnt;
    int find(int x)
    {
        if(fa[x]==x)return x;
        return fa[x]=find(fa[x]);
    }
    int main()
    {
        scanf("%d%d%d",&n,&m,&p);
        for(int i=1;i<=n;i++)fa[i]=i;
        for(int i=1;i<=p;i++)
        {
            int x,y;
            scanf("%d%d",&x,&y);
            int a=find(x),b=find(y);
            if(a!=b)fa[a]=b;
        }
        for(int i=1;i<=n;i++)
        {
            int t=find(i);
            if(!belong[t])
            {
                  v[++cnt]=1;
                  belong[t]=cnt;
            }
            else v[belong[t]]++;
        }
        f[0]=1;
        for(int i=1;i<=cnt;i++)
          for(int j=n;j>=v[i];j--)
            if(f[j-v[i]])f[j]=1;
        int minn=M,ans;
        for(int i=0;i<=n;i++)
          if(f[i]&&abs(i-m)<minn)
          {
              minn=abs(i-m);
              ans=i;
          }
        printf("%d",ans);
        return 0;
    }
    View Code
  • 相关阅读:
    百度brpc 压测工具rpc_press解析
    Reactor反应器模式 (epoll)
    hive和hbase的区别
    Hive和HBase
    入门HBase,看这一篇就够了
    Docker保存修改后的镜像
    怎样将本地文件上传到docker容器
    Docker 安装tomcat访问空白页问题解决办法
    Centos中查看系统信息的常用命令
    Docker 镜像加速
  • 原文地址:https://www.cnblogs.com/harden/p/5781446.html
Copyright © 2020-2023  润新知