这是从山东大学巨巨那里学来的做法
枚举下黑色球的排列总数是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; }
时间: 2024-10-13 01:39:52