[Luogu] 选学霸

https://www.luogu.org/problemnew/show/P2170

并查集+DP

#include <iostream>
#include <cstring>
#include <cmath>
using namespace std;
const int maxn=20005;
int n,m,k,tot;
int p[maxn];
int man[maxn];
int f[maxn+maxn];
int find(int x) {
    return (x==p[x]?x:p[x]=find(p[x]));
}
void solve() {
    memset(f,0,sizeof(f));
    for(int i=1; i<=tot; i++)
        for(int j=2*m; j>=man[i]; j--)
            f[j]=max(f[j],f[j-man[i]]+man[i]);
    for(int i=0; i<=m; i++) {
        if(f[m-i]==m-i) {
            cout<<m-i<<endl;
            return;
        }
        if(f[m+i]==m+i) {
            cout<<m+i<<endl;
            return;
        }
    }
    return;
}
int main() {
    cin>>n>>m>>k;
    int u,v;
    for(int i=1; i<=n; i++)
        p[i]=i;
    for(int i=1; i<=k; i++) {
        cin>>u>>v;
        int x=find(u);
        int y=find(v);
        p[x]=y;
    }
    memset(man,0,sizeof(man));
    for(int i=1; i<=n; i++)
        man[find(i)]++;
    tot=0;
    for(int i=1; i<=n; i++)
        if(man[i]!=0) man[++tot]=man[i];
    solve();
    return 0;
}

 

posted @ 2018-01-06 18:59  xayata  阅读(127)  评论(0编辑  收藏  举报