题意: 给出n个yang珠子n个yin珠子。
给出抵消的编号
询问排成环,最少可以形成个被抵消的yang珠子
思路:
枚举yang珠子在yin珠子排列的可能。一次求出不抵消的匹配 数,那么抵消的=n-不抵消的
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
const int maxn=105;
int mp[maxn][maxn];//mp数组存的是阴阳珠是否抵消
int a[maxn];//用来存储排列的方式
int vec[maxn][maxn];
int pre[maxn];
int vis[maxn];
int n;
bool dfs(int u)
{
for(int v=1; v<=n; v++)
{
if(vec[u][v]&&!vis[v])
{
vis[v]=true;
if(pre[v]==-1||dfs(pre[v]))
{
pre[v]=u;
return true;
}
}
}
return false;
}
int hungary()
{
int res=0;
memset(pre,-1,sizeof(pre));
for(int u=1; u<=n; u++)
{
memset(vis,0,sizeof(vis));
if(dfs(u))
res++;
}
return res;
}
int main()
{
int m;
while(~scanf("%d%d",&n,&m))
{
if(n==0)
{
printf("0\n");
continue;
}
memset(mp,0,sizeof(mp));
for(int i=1; i<=m; i++)
{
int a,b;
scanf("%d%d",&a,&b);
mp[a][b]=1;
}
///mp 表示 a号阳珠子 与b号阴珠子 抵消
int ans=0x3f3f3f3f;
for(int i=1; i<=n; i++)
a[i]=i;
///初始化,之后枚举阳珠插到阴珠子的情况
do
{
memset(vec,0,sizeof(vec));
for(int i=1; i<=n; i++) ///i 阳,j 阴
{
for(int j=1; j<=n; j++)
{
int l=a[j],r=a[j+1];
if(j==n)
r=a[1];
if(!mp[i][l]&&!mp[i][r])
{
vec[i][j]=1;
}
}
}
int num=hungary();
///最大匹配到的未抵消的数量 =n - 抵消掉的
ans=min(ans,n-num);
}
while(next_permutation(a+2,a+n+1));
printf("%d\n",ans);
}
return 0;
}