zoukankan      html  css  js  c++  java
  • 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
    ",++T,ans);
    	}
    }
    

      

  • 相关阅读:
    云题库错题分析
    数据库相关子查询
    阻止事件冒泡
    21分钟 MySQL 入门教程(转载!!!)
    java接口
    java访问修饰符
    小游戏,快速击键
    个人对Java中多态的一些简单理解
    简述抽象和封装,对你学习Java有一些作用
    Bank,我只是来完成作业的
  • 原文地址:https://www.cnblogs.com/TheRoadToTheGold/p/7673851.html
Copyright © 2011-2022 走看看