您的位置:首页 > 其它

HDU5727 Necklace(枚举 + 二分图最大匹配)

2016-07-20 17:11 555 查看
题目大概说有n个yang珠子n个yin珠子,要交替串成一个环形项链,有些yang珠子和某个yin珠子相邻这个yang珠子会不高兴,问最少有几个yang珠子不高兴。

自然会想到直接用状压DP去解,转移很烦,也没写出来。标程是搜索不明觉厉。。听闻了可以枚举一边的顺序,8!,然后用最大匹配解决。

然后想到的是枚举yang的顺序,然后对于每一个yang去其匹配下一个的yin,即X部是yang,而Y部是yin。不过这样开头那个yang可能出现少算的情况。。这个搞了好久都不行。。

其实,枚举yin的顺序,X部是各个yang,而Y部是位置!然后问题就引刃而解。我太菜了。。

另外用最大流超时了,然后用了个匈牙利过了,O((n-1)!*n3)的时间复杂度。

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;

int n,map[22][22],mat[22];
bool used[22];
bool crosspath(int k){
for(int i=1; i<=map[k][0]; ++i){
int j=map[k][i];
if(!used[j]){
used[j]=true;
if(mat[j]==0 || crosspath(mat[j])){
mat[j]=k;
return true;
}
}
}
return false;
}

int hungary(){
int res=0;
for(int i=1; i<=n; ++i){
memset(used,0,sizeof(used));
if(crosspath(i)) ++res;
}
return res;
}

bool rel[11][11];
int main(){
int m;
while(~scanf("%d%d",&n,&m)){
memset(rel,0,sizeof(rel));
int a,b;
while(m--){
scanf("%d%d",&a,&b);
rel[a][b]=1;
}

if(n==1 && rel[1][1]){
puts("1");
continue;
}
if(n<=1){
puts("0");
continue;
}

int seq[11];
for(int i=1; i<=n; ++i){
seq[i]=i;
}

int res=0;
do{
for(int i=1; i<=2*n; ++i) map[i][0]=0;
memset(mat,0,sizeof(mat));
for(int i=1; i<=n; ++i){
for(int j=1; j<=n; ++j){
if(rel[i][seq[j]] || rel[i][seq[j%n+1]]) continue;
map[i][++map[i][0]]=j+n;
map[j+n][++map[j+n][0]]=i;
}
}
res=max(res,hungary());
}while(next_permutation(seq+2,seq+1+n));
printf("%d\n",n-res);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: