hdu5313 Bipartite Graph (dp+bitset优化)

题目链接:

http://acm.hdu.edu.cn/showproblem.php?pid=5313 

 

题目大意:

给定一个二分图(可能不连通),问最多可以加多少边使其仍是二分图

 2n10000,0m100000

n是顶点数,m为边数

 

Solution:

直接dp O(n^2)会超时 (dp[i][j] 表示前i个连通二分图能否可以凑成j个)

看题解发现居然有bitset这种东西

可以将里面的一个循环简化成移位和按位或

 

//#define __LOCAL
//#define __LLD

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <time.h>
#include <algorithm>
#include <queue>
#include <vector>
#include <stack>
#include <set>
#include <bitset>
#include <map>
#include <iostream>
using namespace std;
typedef long long LL;
typedef pair<int,int> PII;
const int ninf = 0x80000000;
const int inf = 0x7FFFFFFF;
const LL INF = (LL)inf*inf;

#ifdef __LLD
    #define printLLln(x) printf("%lld\n", x)
    #define printLL(x) printf("%lld", x)
#else
    #define printLLln(x) printf("%I64d\n", x)
    #define printLL(x) printf("%I64d", x)
#endif

#define MP make_pair
#define PB push_back

//
const int MAXN = 10010;
int n, m;
vector<int> g[MAXN];
int cnt[MAXN][2];
bool vis[MAXN];
int block;
//bool dp[MAXN][MAXN/2];
bitset<MAXN> dp;

void init()
{
    for(int i=0;i<MAXN;++i)
        g[i].clear();
    memset(cnt, 0, sizeof(cnt));
    memset(vis, 0, sizeof(vis));
//    memset(dp, 0, sizeof(dp));
    block = 0;
    dp.reset();

}
void dfs(int v, int color)
{
    vis[v] =  true;
    cnt[block][color]++;
    for(int i=0;i<g[v].size();++i)
    {
        if(!vis[g[v][i]])
            dfs(g[v][i], color^1);
    }
}
void solve()
{
    init();
    scanf("%d%d",&n,&m);
    int u,v;
    for(int i=0;i<m;++i)
    {
        scanf("%d%d",&u,&v);
        g[u].push_back(v);
        g[v].push_back(u);
    }
    for(int i=1;i<=n;++i)
    {
        if(!vis[i]){
            dfs(i, 0);
            block++;
        }
    }
    
    dp[0]=1;
    for(int i=0; i<block; i++)
        dp = (dp<<cnt[i][0]) | (dp<<cnt[i][1]);
    
    
//    dp[0][cnt[0][0]] = true;
//    dp[0][cnt[0][1]] = true;
//    for (int i=1; i<block; ++i) {
//        for (int j=min(cnt[i][0],cnt[i][1]); j<=n/2; ++j) {
//            if (j > cnt[i][0]) {
//                dp[i][j] |= dp[i-1][j-cnt[i][0]];
//            }
//            if (j > cnt[i][1]) {
//                dp[i][j] |= dp[i-1][j-cnt[i][1]];
//            }
//        }
//    }
    
    int ans=0;
    for(int i=0;i<=n/2;++i){
        if(dp[i]){
            ans = max(ans, i*(n-i)-m);
        }
    }
    printf("%d\n",ans);
}
int main()
{
#ifdef __LOCAL
    printf("OK\n");
    freopen("/Users/apple/Documents/xcode/contest/data.in", "r", stdin);
//    freopen("/Users/apple/Documents/xcode/contest/data.out", "w", stdout);
#endif

    int T;
//    int num=0;
    scanf("%d",&T);
    while(T--){
//        printf("Case #%d: ",++num);
        solve();
    }
//
//    int n;
//    while(scanf("%d", &n)!=EOF){
//        solve();
//    }
    return 0;
}
View Code

 

posted @ 2015-07-30 11:35  可乐君  阅读(121)  评论(0编辑  收藏  举报