zoukankan      html  css  js  c++  java
  • b_lg_选学霸(并查集+01背包)

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

    思路
    注意:是与m的差的绝对值最小化,所以选的人数可>m,也可≤m

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int N=2e4+5;
    int n,m,k, fa[N], sz[N], f[N], s[N];
    int find(int u) {
        return fa[u]==u ? u : fa[u]=find(fa[u]);
    }
    void merge(int u, int v) {
        int fu=find(u), fv=find(v);
        if (fu!=fv) {
            fa[fu]=fv;
            sz[fv]+=sz[fu];
        }
    }
    int main() {
        std::ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
        cin>>n>>m>>k;
        for (int i=1; i<=n; i++) fa[i]=i, sz[i]=1;
        for (int i=0; i<k; i++) {
            int u,v; cin>>u>>v;
            merge(u,v);
        }
        int tot=0, cap=min(n,2*m);
        for (int i=1; i<=n; i++) if (fa[i]==i)
            s[tot++]=sz[i];  //每个连通块的人数
        //对于每个连通块都可以选或不选
        for (int i=0; i<tot; i++)
        for (int j=cap; j>=s[i]; j--) {
            f[j]=max(f[j], f[j-s[i]]+s[i]);
        }
        ll ans=-1, mi=INT_MAX;
        for (int j=0; j<=cap; j++) {
            int d=abs(f[j]-m);
            if (d<mi || (d==mi && f[j]<ans)) {
                mi=d, ans=f[j];
            }
        }
        cout<<ans;
        return 0;
    }
    
  • 相关阅读:
    点击cell后 cell的背景不变,cell上的字体颜色发生改变的功能实现
    各种属性设置
    多列表 ,菜单
    正则表达式
    多个storyboard之间的跳转问题
    关于uicollectionview的个人学习
    uiscrollview的自动布局
    手动自动布局
    关于简单的跳转问题
    深入理解@class和#import的区别
  • 原文地址:https://www.cnblogs.com/wdt1/p/13807241.html
Copyright © 2011-2022 走看看