uva 818 (位运算 + 判环)

 Cutting Chains 

What a find! 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 first 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 difficult than she at first 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 specified 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 Output for the 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
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


ACM World Finals 2000, Problem C

题意好难理解,最后才弄明白原来有n个环,编号从1到n,给出了一些环环相扣的情况,比如给1和2表示1和2两个环的扣在一起的,每个环都是可以打开的,问最少打开多少个环,然后再扣好,可以让所有的环成为一条链。

题解:

因为n最大才15,可以用一个二进制数表示各个环是否被打开,然后未被打开的环判断一下是否还有位置度数大于2,以及是否有环的存在,并且保证打开环的数目加1要大于剩余链的数目。

很傻的忘了环编号从1开始,wa了无数遍。。。

#include <cstdio>
#include <iostream>
#include <sstream>
#include <cmath>
#include <cstring>
#include <cstdlib>
#include <string>
#include <vector>
#include <map>
#include <set>
#include <queue>
#include <stack>
#include <algorithm>
using namespace std;
#define ll long long
#define _cle(m, a) memset(m, a, sizeof(m))
#define repu(i, a, b) for(int i = a; i < b; i++)
#define repd(i, a, b) for(int i = b; i >= a; i--)
#define sfi(n) scanf("%d", &n)
#define pfi(n) printf("%d\n", n)
#define sfi2(n, m) scanf("%d%d", &n, &m)
#define pfi2(n, m) printf("%d %d\n", n, m)
#define pfi3(a, b, c) printf("%d %d %d\n", a, b, c)
#define MAXN 16
#define R 6
#define C 7
const int INF = 0x3f3f3f3f;
vector<int> v[MAXN];
bool vis[MAXN];
bool mp[MAXN][MAXN];
bool open[MAXN];

bool dfs(int r, int fa)
{
    if(vis[r]) return true;
    vis[r] = 1;
    int siz = v[r].size();
    int d = siz;
    repu(i, 0, siz)
    {
        if(open[v[r][i]]) d--;
        else if(v[r][i] != fa)
             if(dfs(v[r][i], r)) return true;
    }
    if(d > 2) return true;
    return false;
}
int main()
{
    int n;
    int kase = 0;
    while(~sfi(n) && n)
    {
        kase++;
        _cle(mp, 0);
        int x, y;
        while(1)
        {
            sfi2(x, y);
            if(x == -1 && y == -1) break;
            mp[y][x] = mp[x][y] = 1;
        }
        repu(i, 1, n + 1)
        {
            v[i].clear();
            repu(j, 1, n + 1) if(mp[i][j]) v[i].push_back(j);
        }
        int minn = n;
        int lim = 1<<n;
        int flag;
        repu(i, 0, lim)
        {
            flag = 0;
            _cle(vis, 0); _cle(open, 0);
            int tot = 0, t = 0;
            repu(j, 0, n)
              if((1<<j) & i) tot++, open[j + 1] = 1;//由于这个j + 1这我一直没加1,wa了无数遍
            repu(j, 1, n + 1)
               if(!open[j] && !vis[j])
               {
                   t++;
                   if(dfs(j, -1)) { flag = 1; break; }
               }
            if(!flag && t <= tot + 1) minn = min(tot, minn);
        }
        printf("Set %d: Minimum links to open is %d\n", kase, minn);
    }
    return 0;
}

时间: 2024-08-09 02:20:59

uva 818 (位运算 + 判环)的相关文章

POJ 1781 In Danger Joseph环 位运算解法

Joseph环,这次模固定是2.假设不是固定模2,那么一般时间效率是O(n).可是这次由于固定模2,那么能够利用2的特殊性,把时间效率提高到O(1). 规律能够看下图: watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQva2VuZGVuMjM=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" > 具体具体解析请看大师Knuth的Concrete m

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

题意:有 n 个圆环,其中有一些已经扣在一起了,现在要打开尽量少的环,使所有的环可以组成一条链. 析:刚开始看的时候,确实是不会啊....现在有点思路,但是还是差一点,方法也不够好,最后还是参考了网上的题解,大神们的代码就是不一样, 但还是看了好久才看懂.首先是用二进制法进行暴力,因为 n 最大才是15,不会超时的,然后就是在暴力时判断打开这些环时,剩下的是不是还存在环, 如果存在那么不是不行的,然后再判断是不是有的环有两个分支以上,因为一个环如果成链那么最多只有两个分支,所以多于两个的也是不对

【UVA】658 - It&#39;s not a Bug, it&#39;s a Feature!(隐式图 + 位运算)

这题直接隐式图 + 位运算暴力搜出来的,2.5s险过,不是正法,做完这题做的最大收获就是学会了一些位运算的处理方式. 1.将s中二进制第k位变成0的处理方式: s = s & (~(1 << pos)); 将s中二进制第k位变成1的处理方式: s = s | (1 << pos); 2.二进制运算: [1] & : 1 & 1 = 1 , 1 & 0 = 0 , 0 & 0 = 0; 快速判断奇偶性: if(a & 1);//为奇数

位运算专题

首先抱来Matrix67大牛的文章(修改部分内容): 位运算简介及实用技巧(一):基础篇     去年年底写的关于位运算的日志是这个Blog里少数大受欢迎的文章之一,很多人都希望我能不断完善那篇文章.后来我看到了不少其它的资料,学习到了更多关于位运算的知识,有了重新整理位运算技巧的想法.从今天起我就开始写这一系列位运算讲解文章,与其说是原来那篇文章的follow-up,不如说是一个remake.当然首先我还是从最基础的东西说起. 什么是位运算?    程序中的所有数在计算机内存中都是以二进制的形

位运算 使用技巧

位运算简介及实用技巧(一):基础篇 什么是位运算? 程序中的所有数在计算机内存中都是以二进制的形式储存的.位运算说穿了,就是直接对整数在内存中的二进制位进行操作.比如,and运算本来是一个逻辑运算符,但整数与整数之间也可以进行and运算.举个例子,6的二进制是110,11的二进制是1011,那么6 and 11的结果就是2,它是二进制对应位进行逻辑运算的结果(0表示False,1表示True,空位都当0处理): 110 AND 1011 ---------- 0010  -->  2 由于位运算

图论/位运算 Codeforces Round #285 (Div. 2) C. Misha and Forest

题目传送门 1 /* 2 题意:给出无向无环图,每一个点的度数和相邻点的异或和(a^b^c^....) 3 图论/位运算:其实这题很简单.类似拓扑排序,先把度数为1的先入对,每一次少一个度数 4 关键在于更新异或和,精髓:a ^ b = c -> a ^ c = b, b ^ c = a; 5 */ 6 #include <cstdio> 7 #include <cstring> 8 #include <cmath> 9 #include <algorith

找唯一不出现三次而出现1次的数子O(n)位运算算法

之前两次那个是异或运算处理.这次以为也是类似.可是没想出来. 高富帅想出来了算法,转为bitset,然后加起来 同样的话 要么0+0+0 要么1+1+1,最后剩下的 能够通过%3 算出0 或1.思想是这样, 事实上也是bit运算.仅仅只是不是异或这样的一次运算O(1)这样的,可是因为输入是int数组,-2^31~2^31-1 所以用32bit就能够表示了. 之前遇到,过几次错误,包含分配存储空间的问题,正如fawks说的.用全局数组,是在全局区域,比栈空间大非常多.所以能够申请大数组,可是lee

位运算简介及实用技巧(一):基础篇[转]

位运算简介及实用技巧(一):基础篇 原贴链接:http://www.matrix67.com/blog/archives/264 去年年底写的关于位运算的日志是这个Blog里少数大受欢迎的文章之一,很多人都希望我能不断完善那篇文章.后来我看到了不少其它的资料,学习到了更多关于位运算的知识,有了重新整理位运算技巧的想法.从今天起我就开始写这一系列位运算讲解文章,与其说是原来那篇文章的follow-up,不如说是一个remake.当然首先我还是从最基础的东西说起. 什么是位运算?    程序中的所有

(转)位运算简介及使用技巧

转自http://www.matrix67.com/blog/archives/263 去年年底写的关于位运算的日志是这个Blog里少数大受欢迎的文章之一,很多人都希望我能不断完善那篇文章.后来我看到了不少其它的资料,学习到了更多关于位运算的知识,有了重新整理位运算技巧的想法.从今天起我就开始写这一系列位运算讲解文章,与其说是原来那篇文章的follow-up,不如说是一个remake.当然首先我还是从最基础的东西说起. 什么是位运算?    程序中的所有数在计算机内存中都是以二进制的形式储存的.