UVa818 Cutting Chains (二进制枚举)

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了UVa818 Cutting Chains (二进制枚举)相关的知识,希望对你有一定的参考价值。

链接:http://vjudge.net/problem/35523

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

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

 

以上是关于UVa818 Cutting Chains (二进制枚举)的主要内容,如果未能解决你的问题,请参考以下文章

UVA 818 Cutting Chains

UVa 818Cutting Chains (暴力dfs+位运算+二进制法)

UVa 818 Cutting Chains 题解

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

UVA10003 Cutting SticksDP

UVA - 10003 —— Cutting Sticks