zoukankan      html  css  js  c++  java
  • UVA 818 Cutting Chains(状压 + 暴搜)题解

    题意:有1~n个小环,他们中的有些互相扣在一起,问你至少切开几个能把这写小环串成一条链

    思路:还是太菜了,题目给的n<=15,显然可以暴力解决。

    用二进制表示每个环切还是不切,然后搜索所有情况。当一种情况满足一下两点:1.切完之后每一串连在一起的环应该是一条链,没有分支没有环;2.当一个环被切开,那么他就可以当做任意串的连接点,那么显然切开的点+1>=串的数量。

    代码:

    #include<set>
    #include<map>
    #include<stack>
    #include<cmath>
    #include<queue>
    #include<vector>
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    typedef long long ll;
    using namespace std;
    const int maxn = 15 + 10;
    const int seed = 131;
    const ll MOD = 100000007;
    const int INF = 0x3f3f3f3f;
    int vis[maxn], del[maxn], mp[maxn][maxn];
    int n, ans, u, v, ca = 1, flag;
    bool branch(){
        int deg = 0;
        for(int i = 1; i <= n; i++){
            deg = 0;
            if(!del[i]){
                for(int j = 1; j <= n; j++){
                    if(mp[i][j] && !del[j])
                        deg++;
                }
            }
            if(deg > 2) return false;
        }
        return true;
    }
    bool dfs(int x, int pre){
        bool yes = true;
        vis[x] = 1;
        for(int i = 1; i <= n; i++){
            if(mp[x][i] && i != pre && !del[i]){
                if(vis[i]) return false;
                yes = dfs(i, x);
                if(!yes) return false;
            }
        }
        return true;
    }
    bool loop(int &rest){
        memset(vis, 0, sizeof(vis));
        flag = 0;
        for(int i = 1; i <= n; i++){
            if(!vis[i] && !del[i]){
                if(!dfs(i, -1)) return false;
                rest++;
            }
        }
        return true;
    }
    int main(){
        while(scanf("%d", &n) && n){
            memset(mp, 0, sizeof(mp));
            while(scanf("%d%d", &u, &v) && u != -1 && v != -1){
                mp[u][v] = mp[v][u] = 1;
            }
            int ans = INF, delet, rest;
            for(int i = 0; i < (1 << n); i++){
                memset(del, 0, sizeof(del));
                delet = rest = 0;
                for(int j = 0; j < n; j++){
                    if(i & (1 << j)){
                        del[j + 1] = 1;
                        delet++;
                    }
                }
                if(!branch() || !loop(rest)) continue;
                //printf("%d
    ", delet);
                if(delet + 1 >= rest){
                    ans = min(ans, delet);
                }
            }
            printf("Set %d: Minimum links to open is %d
    ", ca++, ans);
        }
        return 0;
    }
  • 相关阅读:
    清除Jpanel组件并重绘
    idea配置ssm框架
    java异常机制
    JavaSwing关于GridBagLayout(网格袋布局)的使用
    (趣味哈哈镜)JMF中摄像头相关的问题
    三大WEB服务器(apache lighttpd nginx) 对比分析
    在前台接收jsonp数据(练习)
    cookie存数组的方法
    接口验证每个ip每小时只能访问2次(自己实验:有待改进)
    DOM操作xml数据
  • 原文地址:https://www.cnblogs.com/KirinSB/p/10083643.html
Copyright © 2011-2022 走看看