hdu 5313 Bipartite Graph 贪心+bfs染色

题意:给出一张二分图,问最多在里面能加多少条边,保证还是二分图。

首先可以确定,在最后的二分图中,两个部分的点数差最小,则能保证所加边数最多。那么记录当前二分图两个部分分别的点数,对新的联通块加入当前二分图时,少的那部分点加入当前多的那部分点集中。最后对那些独立的点单独处理,即加入使得两部分的点数差最小。最后就是x*y-m,即两部分点数之积-原图变数

#include <map>
#include <set>
#include <queue>
#include <stack>
#include <cmath>
#include <time.h>
#include <vector>
#include <cstdio>
#include <string>
#include <iomanip>
///cout << fixed << setprecision(13) << (double) x << endl;
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>

using namespace std;

#define lson l, mid, rt << 1
#define rson mid + 1, r, rt << 1 | 1
#define ls rt << 1
#define rs rt << 1 | 1
#define pi acos(-1.0)
#define eps 1e-8
#define Mp(a, b) make_pair(a, b)
#define asd puts("asdasdasdasdasdf");
typedef long long ll;
//typedef __int64 LL;
const int inf = 0x3f3f3f3f;
const int N = 10050;
const ll mod = 1e9+7;

struct node{
	int v, nxt;
}e[N*20];
int head[N];
int col[N];
int deg[N];
queue <int> q;
int n, m, cnt;
int zero, one;
void init()
{
	zero = one = cnt = 0;
	memset( col, -1, sizeof( col ) );
	memset( deg, 0, sizeof( deg ) );
	memset( head, -1, sizeof( head ) );
}


void add( int u, int v )
{
	e[cnt].v = v;
	e[cnt].nxt = head[u];
	head[u] = cnt++;
}

void bfs( int u )
{
	while( !q.empty() )	q.pop();
	int z = 0, x = 0;
	col[u] = 1;
	z++;
	q.push( u );
	while( !q.empty() ) {
		u = q.front();
		q.pop();
		for( int i = head[u]; ~i; i = e[i].nxt ) {
			int v = e[i].v;
			if( col[v] != -1 )
				continue;
			col[v] = !col[u];
			if( col[v] )
				z++;
			else
				x++;
			q.push(v);
		}
	}
	if( z >= x ) {
		zero += z;
		one += x;
	}
	else {
		zero += x;
		one += z;
	}
}

int main()
{
	int tot;
	for( scanf("%d", &tot); tot--; ) {
		init();
		scanf("%d%d", &n, &m);
		for( int i = 1, u, v; i <= m; ++i ) {
			scanf("%d%d", &u, &v);
			deg[u] = deg[v] = 1;
			add( u, v );
			add( v, u );
		}
		int lp = 0;
		for( int i = 1; i <= n; ++i ) {
			if( !deg[i] ) {
				lp++;
				continue;
			}
			if( zero > one )
				swap( zero, one );
			if( col[i] == -1 )
				bfs( i );
		}
		if( zero < one )
			swap( zero, one );
		int cha = zero - one;
		if( lp >= cha ) {
			lp -= cha;
			one += cha;
		}
		zero += lp / 2;
		one += ( lp - lp/2 );
		printf("%lld\n", 1LL * zero * one - 1LL * m );
	}
	return 0;
}

ps:我也觉得加进的联通块策略应该是dp。。可能是数据弱了。。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值