hdu 5313 Bipartite Graph

来源:互联网 发布:皇嘉财润公司知乎 编辑:程序博客网 时间:2024/05/17 07:02



官方题解:

首先二分图可以分成两类点XXYY, 完全二分图的边数就是|X| \cdot |Y|XY.我们的目的是\max {|X| \cdot |Y|}max{XY}, 并且|X| + |Y| = nX+Y=n.

把原图黑白染色, 每个联通块有a_iai个黑点, b_ibi个白点, 于是就是要确定a_iai属于XX还是属于YY. 然后我们考虑dp, dp_{i,x}dpi,x表示用了前ii个联通块, |X|=xX=x是否可行. dp方程很容易确定, dp_{i,x} = dp_{i-1,x-a[i]} \text{ or } dp_{i-1,x-b[i]}dpi,x=dpi1,xa[i] or dpi1,xb[i].

直接暴力是O(n^2)O(n2)的, 可以考虑用bitset优化, 这样就可以过了. 实际上由于数据很难造, 一些稍加优化的n^2n2也可以过的。

不懂bitset或者不会用的童鞋请看:http://blog.csdn.net/piaocoder/article/details/47177891

#include <iostream>#include <cstdio>#include <bitset>#include <algorithm>#define N 110000using namespace std;bitset<11000>ans;int s[N][2],fa[N],n,m,a[N];int find_set(int x){    if(x == fa[x])        return x;    int t = fa[x];    fa[x] = find_set(fa[x]);    a[x] = a[x]^a[t];    return fa[x];}void solved(){    for(int i = 1; i <= n; i++)        ans[i] = 0;    ans[0] = 1;    for(int i = 1; i <= n; i++)        s[find_set(i)][a[i]]++;    for(int i=1;i<=n;i++)    if(fa[i]==i){        //cout<<s[i][0]<<" "<<s[i][1]<<endl;        ans = (ans<<s[i][0])|(ans<<s[i][1]);    }    int maxn=0;    for(int i=0;i<=n;i++)    if(ans[i])        maxn = max(maxn,i*(n-i)-m);    printf("%d\n",maxn);}int main(){    int T;    scanf("%d",&T);    while(T--){        scanf("%d%d",&n,&m);        for(int i = 1; i <= n; i++)            fa[i]=i,s[i][0]=0,s[i][1]=0,a[i]=0;        for(int i=1;i<=m;i++){            int x,y;            scanf("%d%d",&x,&y);            int fx = find_set(x),fy = find_set(y);            if(fx == fy)                continue;            fa[fx] = fy;            a[fx] = 1^a[x]^a[y];        }        solved();    }    return 0;}


0 0