STL 中 next_permutation 用法:
int a[5] = {1,2,3,4,5}; do{ for(int i = 0;i < 5;++i) printf("%d ",a[i]); puts(""); }while(next_permutation(a,a+5));
题意:n个阴珠子n个阳珠子间隔串成一串项链,每一组信息u,v表示u号阳珠子放在v号阴珠子旁边会褪色。求出最少褪色阳珠子的个数。
思路:STL的全排列枚举阴珠子的排列, 然后对于一种排列, 给每一个位置对应的不会褪色的阳珠子建边, 跑出的最大匹配就是最多的不褪色阳珠子个数。
代码:
#include <iostream> #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> using namespace std; struct Edge{ int to,next; }edge[505]; int match[11],head[11]; int to[11]; bool mp[11][11],vis[11]; bool dfs(int u){ for(int i = head[u];i != -1;i = edge[i].next){ int v = edge[i].to; if(!vis[v]){ vis[v] = 1; if(!match[v] || dfs(match[v])){ match[v] = u; to[u] = v; return true; } } } return false; } int a[14]; int main() { int n,m; while(~scanf("%d%d",&n,&m)){ if(n == 0 || m == 0){ puts("0"); continue; } for(int i = 1;i <= n;++i) a[i] = i; memset(mp,0,sizeof(mp)); int u,v; for(int i = 1;i <= m;++i){ scanf("%d%d",&u,&v); mp[u][v] = 1; } int ans = n; do{ memset(head,-1,sizeof(head)); memset(match,0,sizeof(match)); memset(to,0,sizeof(to)); a[0] = a[n]; int cnt = 0; for(int i = 0;i < n;++i){ for(int j = 1;j <= n;++j){ if(!mp[j][a[i]] && !mp[j][a[i+1]]){ edge[cnt].to = i+1,edge[cnt].next = head[j],head[j] = cnt++; } } } int temp = 0; for(int i = 1;i <= n;++i){ memset(vis,0,sizeof(vis)); if(!to[i]) temp += dfs(i); } ans = min(ans,n - temp); if(!ans) break; }while(next_permutation(a+2,a+n+1)); printf("%d\n",ans); } return 0; }
TLE原因:
0.出题人是SB
1. ans = 0时可以直接退出
2.由于是圆排列,所以全排列可以直接从2位置开始做