题目连接:http://acm.hdu.edu.cn/showproblem.php?pid=5727
【题意】有2*n个魔法宝石,其中阳性宝石和阴性宝石各n个。阳宝石和阴宝石必须相间摆放做成一条项链,及同性宝石不可以相邻。给定m个规则,第xi个阳宝石和第yi个阴宝石相邻时阳宝石会变暗,求阳宝石最小变暗数。
【分析】先ORZ一下大神。。表示题解的估价法任然不懂。由于宝石相间分布,所以可以先摆好一种宝石,假定先摆阴宝石,枚举所有阴宝石的摆法,再枚举插入阳宝石。这里认为会变暗的位置为不匹配位置,求取最大匹配值为阳宝石能够插入几个。最后变暗的数目就是n-插入的阳宝石数。
【代码】
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int s[15][15];
int yin[15];
int vis[15];
int link[15];
int g[15][15];
int ans;
int n,m,x,y;
bool dfs(int x){
for(int i=0;i<n;++i)
if(g[x][i] && !vis[i]){
vis[i]=1;
if(link[i]==-1 || dfs(link[i])){
link[i]=x;
return true;
}
}
return false;
}
int max_match(){
int ret=0;
memset(link,-1,sizeof(link));
for(int i=1;i<=n;++i){
memset(vis,0,sizeof(vis));
if(dfs(i))
ret++;
}
return ret;
}
int main(){
while(~scanf("%d %d",&n,&m)){
memset(s,0,sizeof(s));
if(n==0){
cout<<0<<endl;
continue;
}
for(int i=0;i<n;++i)
yin[i]=i+1;
for(int i=0;i<m;++i){
scanf("%d %d",&x,&y);
s[x][y]=1;
}
ans=n;
do{
memset(g,0,sizeof(g));
for(int i=1;i<=n;++i)
for(int j=0;j<n;++j)
if(!s[i][yin[j]] && !s[i][yin[(j+1)%n]])
g[i][j]=1;
ans=min(ans,n-max_match());
}while(next_permutation(yin+1,yin+n));
cout<<ans<<endl;
}
}