poj 1636

题意:有两个元素个数都为N的集合,要交换N/2个元素,但有些元素不能在一起,求最多能交换多少元素?

1号监狱的某a个人和2号监狱的某b个人是被“绑定”的,即这a个人中的任何一个人都不能和那b个人中任何一个人在同一监狱。

比如:1号监狱的5号犯人和2号监狱的8号9号不能在一起,2号监狱的8不能和1中的2,2号监狱的9不能和1的3,那么1中的2 3 5与2中的8 9被“绑定”,必须同生共死!

这样把数据分成若干组,接下来就可以DP了:

现在问题转化为:有p对儿数a[i],b[i],1<=i<=p,选出一些对儿,使SUMa == SUMb并且sum<=m/2

dp:

dp[k][i][j]=dp[k-1][i][j]||dp[k-1][i-a[k]][j-b[k]];

满足dp[k][i][i]为1最大i为所求。

#include<iostream>
#include<fstream>

using namespace std;
int n,m;
int cnt=0;
typedef struct e{
	int data;
	e *next;
}e;

e edge[401];
int v[401];
int a[402],b[402];
int dp[402][402];

void dfs(int s){
	v[s]=1;
	if(s<=n)
		a[cnt]++;
	else
		b[cnt]++;
	e *p=edge[s].next;
	while(p){
		if(!v[p->data])
			dfs(p->data);
		p=p->next;
	}
}

void solve(){
	int i,j,k;
	memset(dp,0,sizeof(dp));
	dp[0][0]=1;
	for(k=1;k<=cnt;k++)
		for(i=n/2;i>=a[k];i--)
			for(j=n/2;j>=b[k];j--)
				dp[i][j]=dp[i][j]||dp[i-a[k]][j-b[k]];

	for(i=n/2;i>=0;i--)
		if(dp[i][i])
			break;
	cout<<i<<endl;
}

void bfs(){
	int i,j,k;
	cnt=0;
	memset(v,0,sizeof(v));
	memset(a,0,sizeof(a));
	memset(b,0,sizeof(b));
	for(i=1;i<=2*n;i++)
		if(v[i]==0)
		{
			cnt++;
			dfs(i);
		}
}
void read(){
//	ifstream cin("in.txt");
	int i,j,k,s,t;
	int K;
	cin>>K;
	while(K--)
	{
		cin>>n>>m;
		for(i=1;i<=2*n;i++)
		{
			edge[i].data=i;
			edge[i].next=0;
		}
		for(i=1;i<=m;i++)
		{
			cin>>j>>k;
			e *p=new e;
			p->data=k+n;
			p->next=edge[j].next;
			edge[j].next=p;
			e *q=new e;
			q->data=j;
			q->next=edge[k+n].next;
			edge[k+n].next=q;
		}
		bfs();
		solve();
	}

}

int main(){
	read();
	return 0;
}

posted on 2011-02-26 15:01  宇宙吾心  阅读(1108)  评论(0)    收藏  举报

导航