Java 实施Karger'的问题;基于联合查找的s最小割算法

Java 实施Karger'的问题;基于联合查找的s最小割算法,java,algorithm,graph,montecarlo,Java,Algorithm,Graph,Montecarlo,我已经使用路径压缩启发式和按秩联合实现了使用联合查找数据结构的Karger算法,但是我遇到了几个问题 我基本上做的是,我运行算法NNlog(N)time来很好地估计答案。然而,我只是没有得到答案的切肉。我每次随机选取一条边,它有两个成员:源“s”和目标“d”。如果它们的父对象不相等,我会合并它们并减少顶点的数量,“vcnt”,它最初等于原始的顶点数。此过程将继续,直到剩下的顶点数为2。最后,我找到每个边的源和目标的父级,如果它们不相等,我增加MinCut计数。这将重复NNLog(N)次 我试着用

我已经使用路径压缩启发式和按秩联合实现了使用联合查找数据结构的Karger算法,但是我遇到了几个问题

我基本上做的是,我运行算法NNlog(N)time来很好地估计答案。然而,我只是没有得到答案的切肉。我每次随机选取一条边,它有两个成员:源“s”和目标“d”。如果它们的父对象不相等,我会合并它们并减少顶点的数量,“vcnt”,它最初等于原始的顶点数。此过程将继续,直到剩下的顶点数为2。最后,我找到每个边的源和目标的父级,如果它们不相等,我增加MinCut计数。这将重复NNLog(N)次

我试着用大量测试数据运行我的代码,但似乎没有得到Mincut值,特别是对于大数据

有人能帮我吗?此外,还欢迎提出绩效改进建议。代码如下:

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);
    }
}    
导入java.io.BufferedReader;
导入java.io.FileInputStream;
导入java.io.IOException;
导入java.io.InputStreamReader;
导入java.util.ArrayList;
Kragersimncut类
{
静态int n=200;//顶点数
静态int[]u=新int[n];
静态int[]秩=新int[n];
静态类Edge//记录源和目标的Edge
{
int s,d;//源,目标
边(整数s,整数d)
{
这个.s=s;
这个。d=d;
}
}
私有静态void InitializeUnionFindData()
{
对于(int i=0;irank[py])
{
int-temp=px;
px=py;
py=温度;
}
else if(秩[px]==秩[py])
秩[py]++;
u[px]=py;
返回true;
}
公共静态void main(字符串[]args)引发IOException
{
BufferedReader br=新的BufferedReader(新的InputStreamReader(System.in));
ArrayList EdgeList=新的ArrayList();

对于(int i=0;i算法表明,每个边都有可能被选择进行合并

但您的代码从不选择索引0处的边

因此,修改行:

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

Edge x=EdgeList.get((int)(Math.random()*(EdgeList.size())));
另外,因为每个边在边列表中列出两次

您应该打印以下内容

System.out.println(MinCut/2);

现在应该可以了。

@bholagabar好的,兄弟,现在我明白了。请看我的最新答案。完成。精彩的观察。非常感谢:D@bholagabbar通过在一个小示例上运行代码。