UVA818-Cutting Chains(二进制枚举+dfs判环)

Problem UVA818-Cutting Chains

Accept:393  Submit:2087

Time Limit: 3000 mSec

 Problem Description

What a ?nd! Anna Locke has just bought several links of chain some of which may be connected. They are made from zorkium, a material that was frequently used to manufacture jewelry in the last century, but is not used for that purpose anymore. It has its very own shine, incomparable to gold or silver, and impossible to describe to anyone who has not seen it ?rst hand. Anna wants the pieces joined into a single end-to-end strand of chain. She takes the links to a jeweler who tells her that the cost of joining them depends on the number of chain links that must be opened and closed. In order to minimize the cost, she carefully calculates the minimum number of links that have to be opened to rejoin all the links into a single sequence. This turns out to be more di?cult than she at ?rst thought. You must solve this problem for her.

 Input

The input consists of descriptions of sets of chain links, one set per line. Each set is a list of integers delimited by one or more spaces. Every description starts with an integer n, which is the number of chain links in the set, where 1 ≤ n ≤ 15. We will label the links 1, 2, ..., n. The integers following n describe which links are connected to each other. Every connection is speci?ed by a pair of integers i,j where 1 ≤ i,j ≤ n and i ?= j, indicating that chain links i and j are connected, i.e., one passes through the other. The description for each set is terminated by the pair ‘-1 -1’, which should not be processed. The input is terminated by a description starting with n = 0. This description should not be processed and will not contain data for connected links.

 Output

For each set of chain links in the input, output a single line which reads
Set N: Minimum links to open is M
where N is the set number and M is the minimal number of links that have to be opened and closed such that all links can be joined into one single chain.

 Sample Input

5 1 2 2 3 4 5 -1 -1

7 1 2 2 3 3 1 4 5 5 6 6 7 7 4 -1 -1

4 1 2 1 3 1 4 -1 -1

3 1 2 2 3 3 1 -1 -1

3 1 2 2 1 -1 -1

0

 Sample Ouput

Set 1: Minimum links to open is 1

Set 2: Minimum links to open is 2

Set 3: Minimum links to open is 1

Set 4: Minimum links to open is 1

Set 5: Minimum links to open is 1

题解:一看到n不超过15,向二进制的方向想是很自然的,顺着思路就出来了,暴力枚举情况,关键在于如何判断一个情况是成立的首先判环是肯定的,然后就是判断断开的个数是否大于等于连通分支的个数-1。这两点都很好想,容易忽略的就是如果一个环的分支数大于2也是不行的。这个虽然不太容易一下想到,但是样例有提示(良心样例),也不是什么困难的问题,代码都是套路。

 1 #include <iostream>
 2 #include <cstring>
 3 #include <cstdlib>
 4 #include <cstdio>
 5 #include <algorithm>
 6 #define INF 0x3f3f3f3f
 7
 8 using namespace std;
 9
10 const int maxn = 20;
11 int n;
12 int gra[maxn][maxn];
13 int vis[maxn];
14
15 bool dfs(const int sit,int fa,int u){
16     vis[u] = -1;
17     for(int v = 0;v < n;v++){
18         if(!gra[u][v] || vis[v]==1 || v==fa || !(sit&(1<<v))) continue;
19         if(vis[v] < 0) return false;
20         if(!vis[v] && !dfs(sit,u,v)) return false;
21     }
22     vis[u] = 1;
23     return true;
24 }
25
26 bool check(const int sit,int &res){
27     memset(vis,0,sizeof(vis));
28     for(int u = 0;u < n;u++){
29         if(!(sit&(1<<u))) continue;
30         if(!vis[u]){
31             if(!dfs(sit,u,u)) return false;
32             res++;
33         }
34     }
35
36     for(int u = 0;u < n;u++){
37         if(!(sit&(1<<u))) continue;
38         int cnt = 0;
39         for(int v = 0;v < n;v++){
40             if(gra[u][v] && sit&(1<<v)) cnt++;
41             if(cnt > 2) return false;
42         }
43     }
44     return true;
45 }
46
47 int iCase = 1;
48
49 int main()
50 {
51     while(~scanf("%d",&n) && n){
52         int x,y;
53         memset(gra,0,sizeof(gra));
54         while(scanf("%d%d",&x,&y) && (x!=-1 && y!=-1)){
55             x--,y--;
56             gra[x][y] = gra[y][x] = 1;
57         }
58         int Min = INF;
59         for(int i = (1<<n)-1;i >= 0;i--){
60             int res = 0;
61             if(check(i,res)){
62                 int cnt = 0;
63                 for(int j = 0;j < n;j++){
64                     if(!(i&(1<<j))) cnt++;
65                 }
66                 if(res-1 <= cnt) Min = min(Min,cnt);
67                 if(Min == 0) break;
68             }
69         }
70         printf("Set %d: Minimum links to open is %d\n",iCase++,Min);
71     }
72     return 0;
73 }

原文地址:https://www.cnblogs.com/npugen/p/9572835.html

时间: 2024-10-03 21:23:09

UVA818-Cutting Chains(二进制枚举+dfs判环)的相关文章

UVa818 Cutting Chains (二进制枚举)

链接:http://vjudge.net/problem/35523 分析:links记录初始圆环链的情况,然后二进制枚举编号为0~n-1的圆环哪个被打开了,一个圆环最多一个前驱和一个后继,所以judge判断如果有一个未打开的圆环同时和2个以上的未打开圆环相连就一定不能形成链,剪去.circle判断剩下的未打开圆环是否形成环,以及若未成环那么有多少条单链links_num,注意最后成链不用按顺序比如1->2->3...这样.然后判断一下打开的圆环数够不够把links_num条单链扣成一条链,若

UVA-818 Cutting Chains (位压缩+暴力搜索)

题目大意:一种环能打开和闭合.现在有n(1<=n<=15)个编号为1~n的环错综复杂的连接着,要打开一些环重新连接使这n个环能构成一条链,问最少需要打开几次环可达到目的? 题目分析:用二进制数表示要打开的环的集合,总共2^n种情形,枚举每一种情况.当把将要打开的环打开后,此环是孤立的,接下来就要判断剩下的环还与几个环连着,如果有的环仍然与两个以上的环连着则该方案不可行,不可能构成链:然后判断剩下的环有没有连成一个圈,如果有,则该方案不可行:最后,判断完前两个条件之后,所有的环都一定处于某条短链

2018 计蒜之道复赛 贝壳找房魔法师顾问(并查集+dfs判环)

贝壳找房在遥远的传奇境外,找到了一个强大的魔法师顾问.他有 22 串数量相同的法力水晶,每个法力水晶可能有不同的颜色.为了方便起见,可以将每串法力水晶视为一个长度不大于 10^5105,字符集不大于 10^5105 的字符串.现在魔法师想要通过一系列魔法使得这两个字符串相同.每种魔法形如 (u,\ v),\ u,\ v \le 10^5(u, v), u, v≤105,可以将一个字符 uu改成一个字符 vv,并且可以使用无限次.出于种种原因,魔法师会强行指定这两个串能否进行修改. 若失败输出 -

CodeForces 711D Directed Roads (DFS判环+计数)

题意:给定一个有向图,然后你可能改变某一些边的方向,然后就形成一种新图,让你求最多有多少种无环图. 析:假设这个图中没有环,那么有多少种呢?也就是说每一边都有两种放法,一共有2^x种,x是边数,那么如果有环呢?假设x是这个连通块的边数, y是这个环的边数,那么就一共有2^x * (2 ^ y - 2) 种,减去这两种就是一边也不变,和所有的边都就变,这样就形成环了. 那么怎么计算呢?这个题的边很特殊,所以我们可以利用这个特征,我们在每个连通块时,用vis记录一下开始的父结点,用cnt记录每一个到

Codeforces 711 D. Directed Roads (DFS判环)

题目链接:http://codeforces.com/problemset/problem/711/D 给你一个n个节点n条边的有向图,可以把一条边反向,现在问有多少种方式可以使这个图没有环. 每个连通量必然有一个环,dfs的时候算出连通量中点的个数y,算出连通量的环中点的个数x,所以这个连通量不成环的答案是2^(y - x) * (2^x - 2). 最后每个连通量的答案相乘即可. 1 //#pragma comment(linker, "/STACK:102400000, 102400000

hdu4975 网络流解方程组(网络流+dfs判环或矩阵DP)

http://acm.hdu.edu.cn/showproblem.php?pid=4975 A simple Gaussian elimination problem. Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 579    Accepted Submission(s): 194 Problem Description Drag

hdu4888 Redraw Beautiful Drawings 最大流+判环

hdu4888 Redraw Beautiful Drawings Time Limit: 3000/1500 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 2007    Accepted Submission(s): 447 Problem Description Alice and Bob are playing together. Alice is crazy abou

UVa 818 切断圆环链(dfs+二进制枚举)

https://vjudge.net/problem/UVA-818 题意:有n个圆环,其中有一些已经扣在了一起.现在需要打开尽量少的圆环,使得所有圆环可以组成一条链,例如,有5个圆环,1-2,2-3,4-5,则需要打开一个圆环,如圆环4,然   后用它穿过圆环3和圆环5后再次闭合4,就可以形成一条链:1-2-3-4-5. 思路:从n个圆环中任意选择圆环,这就是枚举子集.所以这道题目可以用二进制枚举来做. 那么如何判断当前打开圆环是可行的呢?在去除打开的圆环后需要判断: ①:每个圆环的分支数都必

【dfs判负环】BZOJ1489: [HNOI2009]最小圈

Description 找出一个平均边权最小的圈. Solution 经典问题,二分答案判断有无负环. 但数据范围大,普通spfa会超时,于是用dfs判负环(快多了). 思路是dis设为0,枚举每个点u,如果d(u)+w<d(v)就搜v,如果搜到的节点曾搜到过说明找到了负环. 感慨一下dfs真是神奇. Code 1 #include<cstdio> 2 #include<algorithm> 3 #include<cstring> 4 using namespac