HDU 5727 Necklace(全排列+二分图匹配)
http://acm.split.hdu.edu.cn/showproblem.php?pid=5727
题意:
现在有n个阳珠子和n个阴珠子,现在要把它们串成项链,要求是阴阳珠子间隔串,但是有些阴阳珠子在一起会让阳珠子变弱,现在问你串起来之后最少有几个阳珠子会变弱。
思路:
很考验思维的一道题目啊~
珠子一共也就9个,阴珠子是固定的,现在就可以先枚举阴珠子的排列顺序(可以用STL自带的全排列),然后对于阳珠子,看看它可以串在哪个位置(和前后两个阴珠子都可以相连),可以的话则连边。这样最后求个最大匹配即可。
不过这题很卡时间,在全排列的时候,因为是环排,所以只需要排n-1位即可,否则会TLE!
1 #include<iostream> 2 #include<algorithm> 3 #include<cstring> 4 #include<cstdio> 5 #include<vector> 6 #include<stack> 7 #include<queue> 8 #include<cmath> 9 #include<map> 10 #include<set> 11 using namespace std; 12 typedef long long ll; 13 typedef pair<int,int> pll; 14 const int INF = 0x3f3f3f3f; 15 const int maxn = 1e5 + 5; 16 17 int ans; 18 int n, m; 19 int a[10]; 20 bool unable[10][10]; 21 bool vis[10]; 22 int mark[10]; 23 24 vector<int> G[10]; 25 26 bool match(int u) 27 { 28 for(int i=0;i<G[u].size();i++) 29 { 30 int v=G[u][i]; 31 if(!vis[v]) 32 { 33 vis[v]=true; 34 if(mark[v]==-1 || match(mark[v])) 35 { 36 mark[v]=u; 37 return true; 38 } 39 } 40 } 41 return false; 42 } 43 44 void solve() 45 { 46 for(int i=0;i<10;i++) G[i].clear(); 47 for(int i=1;i<=n;i++) 48 { 49 for(int j=1;j<=n;j++) 50 { 51 int nxt=i,pre=i-1; 52 if(pre==0) pre=n; 53 if(!unable[j][a[pre]] && !unable[j][a[nxt]]) 54 G[j].push_back(i); 55 } 56 } 57 58 memset(mark,-1,sizeof(mark)); 59 int sum=0; 60 for(int i=1;i<=n;i++) 61 { 62 memset(vis,false,sizeof(vis)); 63 if(match(i)) sum++; 64 } 65 ans=min(ans,n-sum); 66 } 67 68 int main() 69 { 70 //freopen("in.txt","r",stdin); 71 while(~scanf("%d%d",&n,&m)) 72 { 73 memset(unable,false,sizeof(unable)); 74 while(m--) 75 { 76 int u,v; 77 scanf("%d%d",&u,&v); 78 unable[u][v]=true; 79 } 80 if(n==0 || m==0) {puts("0");continue;} 81 ans=INF; 82 for(int i=1;i<=n;i++) a[i]=i; 83 do 84 { 85 solve(); 86 }while(next_permutation(a+1,a+n)); //因为是个环,所以只需要全排列(n-1)个数就好,少了一个*n的复杂度 87 printf("%d\n",ans); 88 } 89 return 0; 90 }