1. 程式人生 > >HDU 5727 Necklace(全排列+二分圖匹配)

HDU 5727 Necklace(全排列+二分圖匹配)

color algorithm target () mark ++ int turn open

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 }

HDU 5727 Necklace(全排列+二分圖匹配)