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位置开始做