UVA 818 Cutting Chains 切断圆环链 (暴力dfs)

题意就是给一张无向图,去掉某些结点,然后连成一条链,问最少去掉几个结点。

n很小n<=15,所以直接枚举2^15个状态就行啦。

链的条件是1.无环,2.没有度大于2的点,3.把n个散链连起来需要n-1次拼接,去掉的结点数>=n-1。

#include<bits/stdc++.h>
using namespace std;
const int maxn = 15;

int G[maxn][maxn];
int n;


int c[maxn];

bool dfs(int u,int s,int fa)
{
    c[u] = 1;
    for(int v = 0; v < n; v++) if(!((s>>v)&1) && G[u][v] && v != fa) {
        if(c[v] || dfs(v,s,u)) return true;
    }
    return false;
}
int cn;

bool have_circle(int s)
{
    memset(c,0,sizeof(c));
    for(int i = 0;i < n; i++)
        if(!((s>>i)&1) && !c[i] ){
            cn++;
            if(dfs(i,s,-1)) return true;
        }

    return false;
}


bool two(int s)
{
    for(int i = 0; i < n; i++) if(!((s>>i)&1)) {
        int deg = 0;
        for(int j = 0; j < n; j++) if(!((s>>j)&1) && G[i][j]) {
            deg++;
        }
        if(deg>2) return true;
    }
    return false;
}


int cal(int s,int &t){
    t = 0;
    while(s){
        if(s&1) t++;
        s>>=1;
    }
    return t;
}

int main()
{
    //freopen("in.txt","r",stdin);
    int cas = 0;
    while(~scanf("%d",&n)&&n){
        int u,v;
        memset(G,0,sizeof(G));
        while(~scanf("%d%d",&u,&v)&~u){
            G[u-1][v-1] = G[v-1][u-1] = 1;
        }
        int ans = 233;
        for(int s = 0,sz = 1<<n; s < sz; s++){
            cn = 0;
            if(!two(s) && !have_circle(s)){
                int t;
                if(cn-1 <= cal(s,t))
                    ans = min(ans,t);
            }
        }
        printf("Set %d: Minimum links to open is %d\n", ++cas, ans);
    }
    return 0;
}

 

posted @ 2015-07-10 19:17  陈瑞宇  阅读(275)  评论(0编辑  收藏  举报