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;
}
浙公网安备 33010602011771号