UVA 818 Cutting Chains
https://vjudge.net/problem/UVA-818
题意:
有n个圆环,其中有一些已经扣在了一起。现在需要打开尽量少的圆环,使得所有圆环可以组成一条链
n<=15
因为n<=15
二进制枚举子集
1、如果有节点的出度>2,则不能构成链
2、如果有环,则不能构成链
判环方式:有节点被重复访问
3、如果断开环的个数+1<支链的条数,那么不能构成链
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; bool e[16][16],tmp[16][16]; int vis[16],out[16]; int n,ans; void dfs(int x,int y) { for(int i=1;i<=n;i++) if(tmp[x][i] && i!=y) { vis[i]++; if(vis[i]<2) dfs(i,x); } } void solve(int s) { memcpy(tmp,e,sizeof(tmp)); int cnt=0; for(int i=1;i<=n;i++) if(s&(1<<i)) { cnt++; for(int j=1;j<=n;j++) tmp[i][j]=tmp[j][i]=false; } memset(out,0,sizeof(out)); for(int i=1;i<=n;i++) { for(int j=1;j<=n;j++) if(tmp[i][j]) out[i]++; if(out[i]>2) return; } memset(vis,0,sizeof(vis)); int node=0; for(int i=1;i<=n;i++) if(!(s&(1<<i)) && !vis[i]) { vis[i]++; node++; dfs(i,-1); } for(int i=1;i<=n;i++) if(vis[i]>=2) return; if(node>cnt+1) return; ans=min(ans,cnt); } int main() { int u,v,T=0; while(1) { scanf("%d",&n); if(!n) return 0; memset(e,0,sizeof(e)); while(1) { scanf("%d%d",&u,&v); if(u==-1) break; e[u][v]=e[v][u]=true; } ans=15; int s=1<<15; for(int i=0;i<s;i++) solve(i); printf("Set %d: Minimum links to open is %d\n",++T,ans); } }