• 选学霸


    【题目描述】

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

    【输入描述】

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

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

    【输出描述】

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

    【样例输入】

    4 3 2

    1 2

    3 4

    【样例输出】

    2

    【数据范围及提示】

    100%的数据,N,P <= 30000。

    源代码:
    
    #include<cstdio>
    #include<algorithm>
    using namespace std;
    int m,n,k,Num(0),F[30001]={0};
    int V[30001],Belong[30001];
    bool f[30001];
    int Find(int t)
    {
        if (!F[t])
          return t;
        return F[t]=Find(F[t]);
    }
    int main()
    {
        scanf("%d%d%d",&n,&m,&k);
        for (int a=1;a<=k;a++)
        {
            int t1,t2;
            scanf("%d%d",&t1,&t2);
            int T1=Find(t1);
            int T2=Find(t2);
            if (T1!=T2)
              F[T1]=T2;
        }
        for (int a=1;a<=n;a++) //并查集预处理。
        {
            int t=Find(a);
            if (!Belong[t])
            {
                V[++Num]=1;
                Belong[t]=Num;
            }
            else
              V[Belong[t]]++;
        }
        f[0]=true;
        for (int a=1;a<=Num;a++) //情况若能到达,便进行标记。
          for (int b=n;b>=V[a];b--)
            if (f[b-V[a]])
              f[b]=true;
        int Min=30000,ans;
        for (int a=0;a<=n;a++) //对于能够到达的情况便进行处理。
          if (f[a]&&abs(a-m)<Min)
          {
            Min=abs(a-m);
            ans=a;
          }
        printf("%d",ans);
        return 0;
    }
  • 相关阅读:
    CF1095F Make It Connected
    【ZJOI2016】旅行者
    [COCI 2009] OTOCI / 极地旅行社
    Sum in the tree
    MST Unification
    【集训队作业2018】Simple Tree
    [COCI2009]Dvapravca
    python 网络编程-02 多进程的交互案例
    python 日志模块logging
    python 网络编程-01基础
  • 原文地址:https://www.cnblogs.com/Ackermann/p/5780158.html
Copyright © 2020-2023  润新知