算法设计与分析: 6-3 最小权顶点覆盖问题

6-3 最小权顶点覆盖问题


问题描述

给定一个赋权无向图 G=(V,E),每个顶点 v∈V 都有一个权值 w(v)。如果 UV U ⊆ V ,且对任意(u,v)∈E 有 u∈U 或 v∈U,就称 U 为图 G 的一个顶点覆盖。G 的最小权顶点覆盖是指 G 中所含顶点权之和最小的顶点覆盖。

对于给定的无向图 G,设计一个优先队列式分支限界法,计算 G 的最小权顶点覆盖。

数据输入:
第 1 行有 2 个正整数 n 和 m,表示给定的图 G 有 n 个顶点和 m 条边,顶点编号为 1,2,…,n。第 2 行有 n 个正整数表示 n 个顶点的权。接下来 的 m 行中,每行有 2 个正整数 u,v,表示图 G 的一条边(u,v)。


Java

package Chapter6FenZhiXianJieFa;

import java.util.PriorityQueue;
import java.util.Queue;
import java.util.Scanner;

public class ZuiXiaoQuanDingDianFuGai {

    private static class HeapNode implements Comparable{
        int i,cn;
        int[] x,c;

        public int compareTo(Object o){
            HeapNode heapNode = (HeapNode) o;
            int result = Integer.compare(cn, heapNode.cn);

            return result;
        }
    }

    private static int u,v;
    private static int n,e;
    private static int[][] a;
    private static int[] p;

    public static void main(String[] args){
        Scanner input = new Scanner(System.in);

        while (true){
            n = input.nextInt();
            e = input.nextInt();

            a = new int[n+1][n+1];
            p = new int[n+1];

            for(int i=0; i<=n; i++)
                for(int j=0; j<=n; j++)
                    a[i][j] = 0;

            for(int i=1; i<=n; i++)
                p[i] = input.nextInt();

            for(int i=1; i<=e; i++){
                u = input.nextInt();
                v = input.nextInt();
                a[u][v] = 1;
                a[v][u] = 1;
            }

            System.out.println(minCover(a,p,n));
            for(int i=1; i<=n; i++)
                System.out.print(p[i]+" ");
        }
    }

    private static class VC{
        int[][] a;
        int[] w,bestx;
        int n,bestn;

        private void BBVC(){
            Queue H = new PriorityQueue<>(100000);
            HeapNode E = new HeapNode();
            E.x = new int[n+1];
            E.c = new int[n+1];
            for(int j=1; j<=n; j++) {E.x[j]=E.c[j]=0;}
            int i=1,cn=0;
            while (true){
                if(i > n){
                    if(cover1(E)){
                        for(int j=1; j<=n; j++) bestx[j]=E.x[j];
                        bestn = cn;
                        break;
                    }
                }else{
                    if(!cover1(E)) addLiveNode(H,E,cn,i,1);
                    addLiveNode(H,E,cn,i,0);
                }
                if(H.size() == 0) break;
                E = H.poll();
                cn = E.cn;
                i = E.i+1;
            }
        }

//        private boolean cover(HeapNode E){
//            for(int j=1; j<=n; j++)
//                if(E.x[j]==0 && E.c[j]==0) return false;
//
//            return true;
//        }

        private boolean cover1(HeapNode E){
            for(int i=1; i<=n; i++)
                for(int j=1; j<=n; j++)
                    if(a[i][j]>0 && E.x[i]==0 && E.x[j]==0)
                        return false;

            return true;
        }

        private void addLiveNode(Queue H, HeapNode E, int cn, int i, int ch){
            HeapNode N = new HeapNode();
            N.x = new int[n+1];
            N.c = new int[n+1];
            for(int j=1; j<=n; j++){
                N.x[j] = E.x[j];
                N.c[j] = E.c[j];
            }
            N.x[i] = ch;
            if(ch > 0){
                N.cn = cn+w[i];
                for(int j=1; j<=n; j++)
                    if(a[i][j] > 0) N.c[j]++;
            }else N.cn=cn;
            N.i = i;
            H.add(N);
        }
    }

    private static int minCover(int[][] a, int[] v, int n){
        VC Y = new VC();
        Y.w = new int[n+1];
        for(int j=1; j<=n; j++) {Y.w[j]=v[j];}
        Y.a=a; Y.n=n; Y.bestx=v;
        Y.BBVC();

        return Y.bestn;
    }
}

Input & Output

7 7
1 100 1 1 1 100 10
1 6
2 4
2 5
3 6
4 5
4 6
6 7
14
1 0 1 1 1 0 1 

Reference

王晓东《计算机算法设计与分析》(第3版)P225

你可能感兴趣的:(Algorithm,Java,计算机算法设计与分析,分支限界法,计算机算法设计与分析)