Necklace
题目链接
题目大意
现在有n颗阳珠子,n颗阴珠子,我们需要用这2n颗珠子排成一个项链,要求阴阳相间。除此以外,某些珠子在一起还会互相影响,现在要求某种排列,使得受到影响的阳珠子数目最少。
题解
二分图最大匹配
因为是一个环,所以我们只用考虑 (n−1)! 种排列就行了,我们首先枚举阴珠子的排列,然后对于某个位置,如果该位置可以放阳珠子,就建一条边,最后用n减去最大匹配数就是受影响的阳珠子的数目。
- 注意n=0的情况要输出0…
代码
#include <iostream>
#include <cstring>
#include <cstdio>
#define INF 0x7fffffff
using namespace std;
int n,m,mp[15][15],g[15][15],sta[15],h;
int link[15],ans;
bool flag[15],vis[15];
bool Dfs(int u)
{
for (int i=1;i<=n;i++) if (!vis[i] && g[u][i])
{
vis[i]=1;
if (!link[i] || Dfs(link[i]))
{
link[i]=u;
return 1;
}
}
return 0;
}
int deal(int n)
{
memset(g,0,sizeof(g));
for (int i=1;i<=n;i++)
for (int j=1;j<=n;j++) if (!mp[j][sta[i]] && !mp[j][sta[i-1]]) g[i][j]=1;
int ans=0;
memset(link,0,sizeof(link));
for (int i=1;i<=n;i++)
{
memset(vis,0,sizeof(vis));
if (Dfs(i)) ans++;
}
return ans;
}
void dfs(int depth)
{
if (depth==n)
{
sta[0]=sta[n];
ans=min(n-deal(n),ans);
sta[0]=0;
return ;
}
for (int i=2;i<=n;i++) if (!flag[i])
{
//if (depth==n-1 && sta[1]>i) return ;
flag[i]=1;
sta[h++]=i;
dfs(depth+1);
sta[--h]=0;
flag[i]=0;
}
}
int main()
{
while (scanf("%d%d",&n,&m)!=EOF)
{
if (n==0)
{
printf("0\n");
continue;
}
memset(sta,0,sizeof(sta));
memset(flag,0,sizeof(flag));
memset(mp,0,sizeof(mp));
int a,b;
for (int i=0;i<m;i++)
{
scanf("%d%d",&a,&b);
mp[a][b]=1;
}
h=1;
sta[h++]=1; flag[1]=1;
ans=INF;
dfs(1);
printf("%d\n",ans);
}
return 0;
}