算法设计与分析: 6-4 无向图的最大割问题

6-4 无向图的最大割问题


问题描述

给定一个无向图 G=(V,E),设 UV U ⊆ V 是 G 的顶点集。对任意(u,v)∈E,若有 u∈U 且v∈V-U,就称(u,v)为关于顶点集 U 的一条割边。顶点集 U 的所有割边构成图 G 的一个割。 G 的最大割是指 G 中所含边数最多的割。

对于给定的无向图 G,设计一个优先队列式分支限界法,计算 G 的最大割。

数据输入:
第 1 行有 2 个正整数 n 和 m,表示给定的图 G 有 n 个顶点和 m 条边,顶点编号为 1,2,…,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 WuXiangTuDeZuiDaGe {

    private static class HeapNode implements Comparable{
        int i,cut,e;
        int[] x;

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

            return result;
        }
    }

    private static int n,e,u,v;
    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<=e; i++){
                u = input.nextInt();
                v = input.nextInt();
                a[u][v] = 1;
                a[v][u] = 1;
            }

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

    private static class MCut{
        int[][] a;
        int[] bestx;
        int n,e,bestn;

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

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

    private static int maxCut(int[][] a, int[] v, int n, int e){
        MCut Y = new MCut();
        Y.a=a; Y.n=n; Y.e=e; Y.bestn=0; Y.bestx=v;
        Y.BBCut();

        return Y.bestn;
    }
}

Input & Output

7 18
1 4
1 5
1 6
1 7
2 3
2 4
2 5
2 6
2 7
3 4
3 5
3 6
3 7
4 5
4 6
5 6
5 7
6 7
12
1 1 1 0 0 0 0 


10 33
1 3
1 6
1 8
1 10
2 3
2 4
2 6
2 7
2 9
2 10
3 4
3 5
3 7
3 8
3 9
3 10
4 5
4 6
4 7
4 8
4 10
5 6
5 7
5 9
6 7
6 8
6 9
6 10
7 9
7 10
8 9
8 10
9 10
22
1 1 0 0 1 0 1 1 0 0

Reference

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

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