您的位置:首页 > 编程语言 > Go语言

Stanford - Algorithms: Design and Analysis, Part 1 - Week 3 Assignment: Contraction

2015-02-22 11:29 3071 查看
本题的题目要求如下:

Download the text file here.
(Right click and save link as)

The file contains the adjacency list representation of a simple undirected graph. There are 200 vertices labeled 1 to 200. The first column in the file represents the vertex label, and the particular row (other entries except the first column) tells all the
vertices that the vertex is adjacent to. So for example, the 6th row
looks like : "6 155 56 52 120 ......". This just means that the vertex with label 6 is adjacent to (i.e., shares an edge with) the vertices with labels 155,56,52,120,......,etc

Your task is to code up and run the randomized contraction algorithm for the min cut problem and use it on the above graph to compute the min cut (i.e., the minimum-possible number of crossing edges). (HINT: Note that you'll have to figure out an implementation
of edge contractions. Initially, you might want to do this naively, creating a new graph from the old every time there's an edge contraction. But you should also think about more efficient implementations.) (WARNING: As per the video lectures, please make
sure to run the algorithm many times with different random seeds, and remember the smallest cut that you ever find.) Write your numeric answer in the space provided. So e.g., if your answer is 5, just type 5 in the space provided.
这次作业我大概编了3小时。。。而且这还是在我数据结构基本都偷懒的情况下。。。只能说俺太弱了。。。。
先说说数据结构吧,

这道题要用图学里面的adjacency list,我就偷懒没有自己装配,直接就用了vector<vector<int>>来搞,我觉得这么着也符合定义,反正这肯定不能算是adjacency matrix。

然后再讲讲这题的算法,其实,这次课程我也听得云里雾里,总之只要是random的东西,感觉都很玄幻。。

不过好在还是把作业做出来了,



上图就是最重要的东西,只要把上面三步装配出来,就能得到解:

第一步:pick a remaining edge (u,v) uniformly at random:

代码如下:

void random_pick(vector<vector<int>>& adjacency_list, int& index_u, int& index_v) {
	
	index_u = rand() % adjacency_list.size();
	int tmp_v = (rand() % (adjacency_list[index_u].size() - 1)) + 1;
	for (int i = 0; i < adjacency_list.size(); ++i)
		if (adjacency_list[i][0] == adjacency_list[index_u][tmp_v]) {
			index_v = i;
			break;
		}
}
这个没啥好解释的,我就是随便取一个u,然后在于他相连的里面随机取v,然后再然会他俩在vector里面的index

第二步:merge u an v into a single vertex:

代码如下:

/* merge the u and v, keep u, delete v */
void merge_vertex(vector<vector<int>>& adjacency_list, int& index_u, int& index_v) {
	for (int i = 0; i < adjacency_list.size(); ++i) {
		if (i != index_v) {
			for (int j = 1; j < adjacency_list[i].size(); ++j) {
				if (adjacency_list[i][j] == adjacency_list[index_v][0])
					adjacency_list[i][j] = adjacency_list[index_u][0];
			}
		}
	}
	for (int i = 1; i < adjacency_list[index_v].size(); ++i)
		adjacency_list[index_u].push_back(adjacency_list[index_v][i]);
}
前面的双重for循环就是把所有跟v相连都改为根u相连

之后的for循环就是把跟v相连的放在u的list里面

这里需要注意,我为了简便运算,就把对vector v的删除放在了下一步中

第三步:remove self-loop

代码如下:

void remove_loop(vector<vector<int>>& adjacency_list, int& index_u, int& index_v) {
	for (int i = 1; i < adjacency_list[index_u].size(); ++i)
		if (adjacency_list[index_u][i] == adjacency_list[index_u][0]) {
			adjacency_list[index_u].erase(adjacency_list[index_u].begin() + i);
			--i;
		}
	adjacency_list.erase(adjacency_list.begin() + index_v);
//	print_adjacency_list(adjacency_list);
}
前面的for循环是删除loop,比如8的list里面有5,6,7,8,8,9,就把所有的8给删除

之后就是将merge中没删除的点给删除。。

以上就是算法的全部过程,

当然,由于contraction是一个random的算法,所以得到正确解得概率很低,我们多次测试才能得到真正的min-cut

下面是完整代码:

# include <iostream>
# include <vector>
# include <fstream>
# include <sstream>
# include <string>
# include <cstdlib>
# include <ctime>
# include <cmath>
# include <climits>
# include <unistd.h>

using namespace std;

const int TIMES = 5000;

/* function prototype */
void store_file(vector<vector<int> >&, string);
void print_adjacency_list(vector<vector<int> >&);
int contraction(vector<vector<int>>&);
void random_pick(vector<vector<int>>&, int&, int&);
void merge_vertex(vector<vector<int>>&, int&, int&);
void remove_loop(vector<vector<int>>&, int&, int&);

int main(int argc, char** argv) {

vector<vector<int> > adjacency_list;
/* store the elements in txt file into adjacency list */
store_file(adjacency_list, "40.txt");
vector<vector<int>> tmp = adjacency_list;
print_adjacency_list(adjacency_list);
srand((unsigned)time(NULL));

/* karger contraction */
int min_cut = INT_MAX;
for (int i = 0; i < TIMES; ++i) {
adjacency_list = tmp;
int inter_val = contraction(adjacency_list);
min_cut = min(inter_val, min_cut);
cout << min_cut << ": " << i << endl;
}
cout << "min-cut: " << min_cut << endl;

return 0;
}

/* store the txt file into adjacency list */
void store_file(vector<vector<int> >& adjacency_list, string filename) {
ifstream infile;
infile.open(filename, ios::in);
string line;
while (getline(infile, line)) {
vector<int> tmp_list;
istringstream istr(line);
int tmp;
while (istr >> tmp)
tmp_list.push_back(tmp);
adjacency_list.push_back(tmp_list);
}
infile.close();
}

/* print the adjacency list */
void print_adjacency_list(vector<vector<int> >& adjacency_list) {
for(int i = 0; i < adjacency_list.size(); ++i) {
for (int j = 0; j < adjacency_list[i].size(); ++j)
cout << adjacency_list[i][j] << " ";
cout << endl;
}
cout << endl;
}

/* karger contraction */
int contraction(vector<vector<int>>& adjacency_list) {
while (adjacency_list.size() > 2) {
int index_u = 0;
int index_v = 0;
random_pick(adjacency_list ,index_u, index_v);
merge_vertex(adjacency_list, index_u, index_v);
remove_loop(adjacency_list, index_u, index_v);
}
return adjacency_list[0].size() - 1;
}

/* random pick edge u-v */
void random_pick(vector<vector<int>>& adjacency_list, int& index_u, int& index_v) { index_u = rand() % adjacency_list.size(); int tmp_v = (rand() % (adjacency_list[index_u].size() - 1)) + 1; for (int i = 0; i < adjacency_list.size(); ++i) if (adjacency_list[i][0] == adjacency_list[index_u][tmp_v]) { index_v = i; break; } }
/* merge the u and v, keep u, delete v */ void merge_vertex(vector<vector<int>>& adjacency_list, int& index_u, int& index_v) { for (int i = 0; i < adjacency_list.size(); ++i) { if (i != index_v) { for (int j = 1; j < adjacency_list[i].size(); ++j) { if (adjacency_list[i][j] == adjacency_list[index_v][0]) adjacency_list[i][j] = adjacency_list[index_u][0]; } } } for (int i = 1; i < adjacency_list[index_v].size(); ++i) adjacency_list[index_u].push_back(adjacency_list[index_v][i]); }

/* remove self-loop */
void remove_loop(vector<vector<int>>& adjacency_list, int& index_u, int& index_v) {
for (int i = 1; i < adjacency_list[index_u].size(); ++i)
if (adjacency_list[index_u][i] == adjacency_list[index_u][0]) {
adjacency_list[index_u].erase(adjacency_list[index_u].begin() + i);
--i;
}
adjacency_list.erase(adjacency_list.begin() + index_v);
}
本次因为时间很赶,我对算法的理解并不好,做的有点着急,,虽然通过了coursera的测试,但是程序中难免会出现错误,希望大家不吝赐教
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: