题意:
两个人数一样的监狱,有一些囚犯不能在一起,两个监狱要等数量( < m/2)交换一些囚犯,问最多可以交换多少个囚犯;
分析:
由题意可知,会有一些联通的块需要同时移动,那我们就把这些联通块求出来,统计一下各个监狱的人数。
然后就变成了 有 z个 联通块 可以选择换还是不换。
就变成了01背包判可行性的问题!
但是 WA的很惨烈。
没有山调试,
清空不彻底
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<vector>
//by mars_ch
using namespace std;
int t;
int m,r;
vector<int> G[505];
int vis[505],q[505],p[505],tot;
int f[1005][1005];
void dfs(int x)
{
if(x<=m) p[tot]++;
else q[tot]++;
vis[x]=1;
for(int i=0;i<G[x].size();i++)
{
if(!vis[G[x][i]])
{
dfs(G[x][i]);
}
}
}
int main()
{
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&m,&r);
for(int i=0;i<=m*2;i++)
{
G[i].clear();
}
memset(vis,0,sizeof(vis));
memset(f,0,sizeof(f));
memset(p,0,sizeof(p));
memset(q,0,sizeof(q));
for(int i=1;i<=r;i++)
{
int a,b;
scanf("%d%d",&a,&b);
G[a].push_back(b+m);
G[b+m].push_back(a);
}
tot=0;
for(int i=1;i<=2*m;i++)
{
if(!vis[i])
{
tot++;
dfs(i);
}
}
int n=m/2;
f[0][0]=1;
for(int i=1;i<=tot;i++)
{
for(int j=n;j>=p[i];j--)
{
for(int k=n;k>=q[i];k--)
{
if(f[j-p[i]][k-q[i]]) f[j][k]=1;
}
}
}
for(int i=n;i>=0;i--)
{
if(f[i][i]) {
printf("%d\n",i);
break;
}
}
}
return 0;
}