简体   繁体   English

使用Union-Find实现Karger的Min Cut算法的问题

[英]Issues in Implementing Karger's Min Cut Algorithm using Union-Find

I've implemented the Karger's algorithm using the Union-Find Datastructure using Path-Compression Heuristics and Union by Rank but I've run into a couple of issues 我已经使用Union-Find数据结构,使用Path-Compression Heuristics和Rank by Union实现了Karger算法,但遇到了两个问题

What I've basically done is, I run the algorithm N N log(N) time for a good estimate of the answer. 我基本上所做的是,我运行算法N N log(N)时间来很好地估计答案。 However, I simply just don't get the answer for the MinCut. 但是,我只是无法获得MinCut的答案。 I pick a random edge each time which has 2 members the source 's' and the destination 'd'. 我每次都选择一个随机边缘,该边缘具有2个成员,即源s和目标d。 If their parents are not equal, I merge them and reduce the count of the vertices, 'vcnt' which was initially equal to the original number of vertices. 如果它们的父母不相等,我将它们合并,并减少顶点数量“ vcnt”,该数量最初等于原始顶点数量。 This process continues until the number of vertices left is 2. Finally, i find the parent of the source and destination of each edge and if they are ont equal, I increase the MinCut count. 这个过程一直持续到剩下的顶点数为2为止。最后,我找到每个边的源和目标的父级,如果它们相等,则增加MinCut计数。 This repeats N N Log(N) times. 这重复N N Log(N)次。

I've tried running my code with a lot of test data but I don't seem to be getting the Mincut Value, Especially for large data. 我尝试使用大量测试数据运行代码,但似乎没有获得Mincut值,尤其是对于大型数据。

Could anyone help me out? 有人可以帮我吗? Also, performance improvement suggestions are welcome. 此外,欢迎提出性能改进建议。 Here is the code: 这是代码:

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;

class KragersMinCut
{
    static int n=200;//Number of Vertices
    static int[] u=new int[n];
    static int[]rank =new int[n];

    static class Edge //Edge which hols the source and destination
    {
        int s,d;//Source,Destination
        Edge(int s,int d)
        {
            this.s=s;
            this.d=d;
        }
    }

    private static void InitializeUnionFindData()
    {
        for(int i=0;i<n;i++)
        {
            u[i]=i;
            rank[i]=1;
        }
    }

    private static int FIND(int xx) //Finding Parent using Path-Compression Heuristics
    {
        if(u[xx]!=u[u[xx]])
        {
            u[xx]=FIND(u[xx]);
        }
        return u[xx];
    }

    private static boolean UNION(int x,int y) //Union by Order-by-Rank to create evenly balanced search trees
    {
    int px=FIND(x),py=FIND(y);
    if(rank[px]>rank[py])
    {
        int temp=px;
        px=py;
        py=temp;
    }
    else if(rank[px]==rank[py])
        rank[py]++;

    u[px]=py;
    return true;
    }


    public static void main(String[] args) throws IOException
    {
        BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
        ArrayList<Edge> EdgeList=new ArrayList<Edge>();
        for(int i=0;i<n;i++)
        {
            String x=br.readLine();
            ArrayList<Integer>al=new ArrayList<Integer>();
            for(int j=0;j<x.length();j++) //This loop is for parsing the input format
            {
                if(x.charAt(j)<48 || x.charAt(j)>57)
                    continue;

                int p=j;
                String input="";
                while(p!=x.length()&&(x.charAt(p)>=48 && x.charAt(p)<=57))
                {
                    input+=(x.charAt(p));
                    p++;
                }
                j=p;
                al.add(Integer.parseInt(input.trim())-1);
            }
            for(int j=1;j<al.size();j++)
            {
                EdgeList.add(new Edge(al.get(0),al.get(j)));//Source,Destination
            }
        }
        //Edge list ready
        int MinCut=Integer.MAX_VALUE;
        for(int q=0;q<(n*n)*Math.log(n);q++)//Running theta(n^2*ln(n)) times for a good estimate. Runs in about 20 secs
        {
            int vcnt=n;//Essentially n
            InitializeUnionFindData();
            while(vcnt>2)
            {
                Edge x=EdgeList.get((int)(Math.random()*(EdgeList.size()-1)+1));//Obtaining random valued element at index from EdgeList
                int s=x.s,d=x.d;
                int ps=FIND(s),pd=FIND(d);
                if(ps!=pd)//Contracting. Essentially making their parents equal
                {
                    UNION(s,d);
                    vcnt--;
                }
            }
            int CurrMinCutValue=0;
            for(Edge i:EdgeList)
            {
                int px=FIND(i.s),py=FIND(i.d);
                if(px!=py)//Since they belong to different Vertices
                {
                    CurrMinCutValue++;
                }
            }
            MinCut=Math.min(MinCut,CurrMinCutValue);//Finding Minimum cut of all random runs
        }
        System.out.println(MinCut);
    }
}    

TestData: (Source Vertex-> Connected Vertices) TestData :(源顶点->连通顶点)

1 2 3 4 7 1 2 3 4 7

2 1 3 4 2 1 3 4

3 1 2 4 3 1 2 4

4 1 2 3 5 4 1 2 3 5

5 4 6 7 8 5 4 6 7 8

6 5 7 8 6 5 7 8

7 1 5 6 8 7 1 5 6 8

8 5 6 7 8 5 6 7

Answer: 4 | 答案:4 | Expected Answer: 2 预期答案:2

Link: http://ideone.com/QP62FN 链接: http//ideone.com/QP62FN

Thanks 谢谢

The algorithm suggests that Every edge is equally likely to be selected for the merging . 该算法建议每个边缘均等地被选择进行合并

But your code never selects the edge at index 0. 但是您的代码永远不会选择索引0处的边。

So modify the line: 因此,修改以下行:

Edge x=EdgeList.get((int)(Math.random()*(EdgeList.size()-1)+1));

to this: 对此:

Edge x=EdgeList.get((int)(Math.random()*(EdgeList.size())));

Also because every edge is listed twice in the edge list: 同样是因为每个边缘在边缘列表中都列出了两次

you should print the following 您应该打印以下内容

System.out.println(MinCut/2);

Now it should work. 现在应该可以了。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM