hdu 5313 Bipartite Graph



官方题解:

首先二分图可以分成两类点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 110000
using 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;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值