链接:http://acm.hdu.edu.cn/showproblem.php?pid=5727
题意:有2*n个宝石,n个阴,n个阳,m条关系(a,b),代表a被b影响,a是阳,b是阴。问将这些宝石组成项链,最少的阳被影响的个数。
分析:我们现在枚举阴的排列,因为是环,所以有(n-1)!种,然后对于每个排列,把阳插入到阴的空隙中,如果空隙两边都没有影响则插入,然后跑一边二分匹配,得出的匹配数(num)就是不受影响的最大数,n-num就最小影响的数目。
代码:
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<string>
#include<vector>
#include<queue>
#include<cmath>
#include<stack>
#include<set>
#include<map>
#define INF 0x3f3f3f3f
#define Mn 1010
#define Mm 2000005
#define mod 1000000007
#define CLR(a,b) memset((a),(b),sizeof((a)))
#define CLRS(a,b,Size) memset((a),(b),sizeof((a[0]))*(Size+1))
#define CPY(a,b) memcpy ((a), (b), sizeof((a)))
#pragma comment(linker, "/STACK:102400000,102400000")
#define ul u<<1
#define ur (u<<1)|1
using namespace std;
typedef long long ll;
int p[10];
int g[10][10];
int mp[10][10];
int lk[10];
int vis[10];
int n;
bool find_path(int u) {
for(int v=1;v<=n;v++) {
if(mp[u][v]&&!vis[v]) {
vis[v]=1;
if(lk[v]==-1||find_path(lk[v])) {
lk[v]=u;
return true;
}
}
}
return false;
}
int main() {
int m;
while(~scanf("%d%d",&n,&m)) {
CLR(g,0);
for(int i=1;i<=m;i++) {
int x,y;
scanf("%d%d",&x,&y);
g[x][y]=1;
}
if(n==0) {
printf("0\n");
continue;
}
int ans=INF;
for(int i=1;i<=n;i++) p[i]=i;
do {
CLR(mp,0);CLR(lk,-1);
for(int i=1;i<=n;i++) {
int x=p[i],y=p[i%n+1];
for(int j=1;j<=n;j++) {
if(!g[j][x]&&!g[j][y]) {
mp[i][j]=1;
}
}
}
int num=0;
for(int i=1;i<=n;i++) {
CLR(vis,0);
num+=find_path(i);
}
ans=min(ans,n-num);
} while(next_permutation(p+2,p+n+1));
printf("%d\n",ans);
}
return 0;
}