HDU5727 Necklace(环排+匈牙利)
这个题是参考网上各大聚聚的代码才写出来的,没办法我太弱了
题意:
给你阴阳珠子各n个,让你串成阴阳相间的串。
给你m种搭配,表示某阳珠子与某阴珠子相邻时会变暗
问你最少有多少阳珠子变暗
思路:
当时想到了可能与二分图有关,但是一直没有什么好的思路
看了网上的题解才恍然大悟
大概就是先枚举阴珠子的所有排列(环排列(n-1)!种)
然后对于每一种排列给不会变暗的阳珠子与阴珠子建边跑匈牙利
得到最大匹配再用n-它
ans取最小的那个就可以了
/* *********************************************** Author :devil Created Time :2016/7/20 17:8:19 ************************************************ */ #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #include <vector> #include <queue> #include <set> #include <map> #include <string> #include <cmath> #include <stdlib.h> using namespace std; typedef long long LL; const int inf=0x3f3f3f3f; const int N=10; int n,m,u,v,ans,pos[N],link[N]; bool s[N][N],vis[N]; vector<int>eg[N]; bool dfs(int u) { for(int i=0;i<eg[u].size();i++) { int v=eg[u][i]; if(!vis[v]) { vis[v]=1; if(link[v]==-1||dfs(link[v])) { link[v]=u; return 1; } } } return 0; } void solve() { memset(s,0,sizeof(s)); while(m--) { scanf("%d%d",&u,&v); s[u][v]=1; } ans=inf; for(int i=1; i<=n; i++) pos[i]=i; do { memset(link,-1,sizeof(link)); for(int i=1; i<=n; i++) { eg[i].clear(); for(int j=1; j<=n; j++) { u=pos[i]; if(i==1) v=pos[n]; else v=pos[i-1]; if(s[j][u]||s[j][v]) continue; eg[i].push_back(j); } } int now=0; for(int i=1; i<=n; i++) { memset(vis,0,sizeof(vis)); now+=dfs(i); } ans=min(ans,n-now); } while(next_permutation(pos+2,pos+n+1)&&ans); printf("%d\n",ans); } int main() { //freopen("in.txt","r",stdin); while(~scanf("%d%d",&n,&m)) { if(!n) { puts("0"); continue; } solve(); } return 0; }