码迷,mamicode.com
首页 > 其他好文 > 详细

HDU 5727 Necklace 二分+匹配

时间:2016-07-20 13:11:29      阅读:111      评论:0      收藏:0      [点我收藏+]

标签:

这是从山东大学巨巨那里学来的做法

枚举下黑色球的排列总数是8!,然后八个白球可选的位置与左右两个黑球存不存在关系建图就行

这是原话,具体一点,每次生成环排,只有互不影响的才连边

最后:注重一点,n个数环排是(n-1)!

技术分享
#include <stdio.h>
#include <iostream>
#include <algorithm>
#include <string.h>
#include <vector>
#include <map>
using namespace std;
typedef long long LL;
const int INF=0x3f3f3f3f;
const int N=2e5+5;
int pos[10],n,m,match[10],ret;
bool vis[10],used[10],g[10][10],mp[10][10];
bool dfs(int u){
  for(int v=1;v<=n;++v){
    if(!g[u][v]||used[v])continue;
    used[v]=true;
    if(match[v]==-1||dfs(match[v])){
      match[v]=u;
      return true;
    }
  }
  return false;
}
void solve(){
  memset(match,-1,sizeof(match));
  memset(g,false,sizeof(g));
  for(int i=2;i<=n;++i){
    for(int j=1;j<=n;++j){
      if(mp[pos[i]][j]||mp[pos[i-1]][j])
        continue;
      g[i][j]=true;
    }
  }
  for(int i=1;i<=n;++i){
    if(mp[pos[1]][i]||mp[pos[n]][i])
      continue;
    g[1][i]=true;
  }
  int ans=0;
  for(int i=1;i<=n;++i){
    memset(used,false,sizeof(used));
    if(dfs(i))++ans;
  }
  ret=min(ret,n-ans);
}
void get(int x){
  if(ret==0)return;
  if(x==n+1){solve();return;}
  for(int i=1;i<=n;++i){
    if(vis[i])continue;
    pos[x]=i;
    vis[i]=true;
    get(x+1);
    vis[i]=false;
  }
}
int main(){  
  vis[1]=true;pos[1]=1;
  while(~scanf("%d%d",&n,&m)){
     if(n==0){
      printf("0\n");
      continue;
     }
     memset(mp,0,sizeof(mp));
     while(m--){
      int u,v;
      scanf("%d%d",&u,&v);
      mp[v][u]=true;
     }
     ret=INF;
     get(2);
     printf("%d\n",ret);
  }
  return 0;
}
View Code

 

HDU 5727 Necklace 二分+匹配

标签:

原文地址:http://www.cnblogs.com/shuguangzw/p/5687761.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!