zoukankan      html  css  js  c++  java
  • 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 InputOutput 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)
    #define sfi2(n, m) scanf("%d%d", &n, &m)
    #define pfi2(n, m) printf("%d %d
    ", n, m)
    #define pfi3(a, b, c) printf("%d %d %d
    ", 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
    ", kase, minn);
        }
        return 0;
    }
    View Code
  • 相关阅读:
    总有一天你将破蛹而出
    java 连接 Access数据库的两种方法
    freemarker中页面直接可以使用的内置对象
    freemarker中页面直接可以使用的内置对象
    常见的样式
    ibatis常用的集中判断语句
    mysql类型转换
    ibatis常用的集中判断语句
    window.open打开窗口时父窗口变成object
    window.open打开窗口时父窗口变成object
  • 原文地址:https://www.cnblogs.com/sunus/p/4786323.html
Copyright © 2011-2022 走看看