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;

}

 

你可能感兴趣的:(chain)