Karger's algorithm to solve global min-cut

#include 
#include 
#include 
#include 
#include 

using namespace std;

struct Edge
{
	int src;
	int dest;
	Edge(int s, int d) : src(s), dest(d) {}
};

struct Graph
{
	int V;	// number of vertices
	vector egdes;
};


// disjoint-set
struct subset
{
	int parent;
	int rank = 0;
};

// find with path compression
int _find(subset subsets[], int i)
{
	// path compression
	if (subsets[i].parent != i)
		subsets[i].parent = _find(subsets, subsets[i].parent);
	
	return subsets[i].parent;
}

// union by rank
void _union(subset subsets[], int x, int y)
{
	int xroot = _find(subsets, x);
	int yroot = _find(subsets, y);
	if (xroot == yroot)
		return;

	// attach smaller rank tree as subtree of higer rank tree
	if (subsets[xroot].rank < subsets[yroot].rank)
		subsets[xroot].parent = yroot;
	else if (subsets[xroot].rank > subsets[yroot].rank)
		subsets[yroot].parent = xroot;
	else
	{
		subsets[xroot].parent = yroot;
		++subsets[yroot].rank;
	}
}

// Karger could return the global min-cut with probability >= 1/(n^2)
int Karger(const Graph &graph, vector &index)
{
	int V = graph.V;
	int E = graph.egdes.size();
	subset *subsets = new subset[V];

	for (int i = 0; i != V; ++i)
	{
		subsets[i].parent = i;
		subsets[i].rank = 0;
	}
	
	int vertices = V;
	while (vertices > 2)
	{
		// pick a random edge
		int i = rand() % E;

		int subset1 = _find(subsets, graph.egdes[i].src);
		int subset2 = _find(subsets, graph.egdes[i].dest);

		// two points belong to same subset
		if (subset1 == subset2)
			continue;

		// contract the edge
		--vertices;
		_union(subsets, subset1, subset2);
	}

	index.clear();
	int cutedges = 0;
	for (int i = 0; i != E; ++i)
	{
		if (_find(subsets, graph.egdes[i].src) != _find(subsets, graph.egdes[i].dest))
		{
			++cutedges;
			index.push_back(i);
		}	
	}

	return cutedges;
}

// n^2ln(n) times repeat, the probability of failing to find min-cut <= 1/(n^2)
void amplify(const Graph &graph, vector &edges)
{
	srand(time(NULL));
	int cutedges = INT_MAX;
	double V = graph.V;
	int loops = static_cast(V * V * log(V));

	for (int i = 0; i != loops; ++i)
	{
		vector index;
		if (Karger(graph, index) < cutedges)
		{
			edges.clear();
			for (int j = 0; j != index.size(); ++j)
				edges.push_back(graph.egdes[index[j]]);
			cutedges = index.size();
		}
		else
			index.clear();
	}
}

int main()
{
	Graph graph;
	graph.V = 6;
	graph.egdes.push_back(Edge(0, 1));
	graph.egdes.push_back(Edge(0, 5));
	graph.egdes.push_back(Edge(0, 2));
	graph.egdes.push_back(Edge(1, 5));
	graph.egdes.push_back(Edge(1, 2));
	graph.egdes.push_back(Edge(1, 3));
	graph.egdes.push_back(Edge(2, 3));
	graph.egdes.push_back(Edge(3, 4));
	graph.egdes.push_back(Edge(4, 5));

	vector edges;
	amplify(graph, edges);

	cout << "Global Min-Cut: " << edges.size() << endl;
	for (auto a : edges)
		cout << a.src << " to " << a.dest << endl;
	
	system("PAUSE");
}

Reference:

http://www.cc.gatech.edu/~vigoda/7530-Spring10/Kargers-MinCut.pdf

你可能感兴趣的:(算法,Min-Cut,Karger)