KM算法实现

今天手撸了一个KM算法 真是惨不忍睹 写了一大长串,但还是贴了出来。通常作为acm的经典入门题,送分罢了。

流程大致是这样:
(1)为每个左边顶点x分配与他连接的边的最大边权。右边y顶点赋值为0.
(2)优先找x.w+y.wweight[x][y]。weight为点x与点y的边的边权。
1.若找到这样的边,且没有占用,占用该边。
2.若找到这样的边,有占用。寻找增广路径。该增广路径同样要求x.w+y.w
weight[x][y]。
若找不到x.w自减一,y.w自加一.
(3)循环步骤2

#include 
#include 
#include 
using namespace std;

bool search_path(const vector<vector<double>> &w,int *p,int *det,int *tra,int num_d,int num_t, set<int> &save_d, set<int> &save_t)
{
	//
	//
	int num_p = p[num_t];
	if (num_p == num_d)
		return 0;
	//优先找没有占用的
	for (int i = 0; i < w[0].size(); i++)
	{
		//
		if (det[num_p] + tra[i] == w[num_p][i]*10)
		{
			if (p[i] == -1)
			{
				p[i] = num_p;
				return 1;
			}
		}
	}
	//没有 就要找增广
	for (int i = 0; i < w[0].size(); i++)
	{
		//
		if (det[num_p] + tra[i] == w[num_p][i]*10)
		{
				if (search_path(w, p, det, tra, num_p, i, save_d, save_t))
				{
					p[i] = num_p;
					return 1;
				}
				else
				{
					//det[num_p] -= 1;
					//tra[i] += 1;
					save_d.insert(num_p);
					save_t.insert(num_t);
					return 0;
				}
		}
	}
	return 0;
}

int* KM(const vector<vector<double>> &w,int th=3)
{
	//int n_detector = w.size();
	if (w.size() == 0)
		return NULL;

	int n_detector = w.size();
	int n_track = w[0].size();
	int *detector;//left weigth in the Bipartite graph
	int *track;//right weigth in the Bipartite graph
	int *p;//tra point to the det
	detector = new int[n_detector];
	p = new int[n_track];
	track = new int[n_track];
	for (int i = 0; i < n_detector; i++)
	{
		detector[i] = 0;
	}
	//distribute the weight
	for (int i = 0; i < n_detector; i++)
	{
		for (int j = 0; j < n_track; j++)
		{
			if (detector[i] < w[i][j]*10)
				detector[i] = w[i][j]*10;
		}
	}
	for (int i = 0; i < n_track; i++)
	{
		track[i] = 0;
		p[i] = -1;
	}

	//search 
	for (int i = 0; i < n_detector; i++)
	{
		//set map;
		while (detector[i]>th)
		{
			bool next = 0;
			bool end = 0;
			set<int> sa_d;
			set<int> sa_t;
			for (int j = 0; j < n_track; j++)
			{
				if (detector[i] + track[j] == w[i][j] * 10)
				{
					if (p[j] == -1)
					{
						p[j] = i;
						next = 1;
						break;
					}
				}
			}
			if (next == 1)
				break;

			for (int j = 0; j < n_track; j++)
			{
				if (detector[i] + track[j] == w[i][j] * 10)
				{
					if (search_path(w, p, detector, track, i, j, sa_d, sa_t))
					{
						p[j] = i;
						next = 1;
						break;
					}
				}
			}
			if (next == 1)
				break;
			for (set<int>::iterator it=sa_d.begin();it!=sa_d.end();it++)
			{
				detector[*it] -= 1;
			}
			for (set<int>::iterator it = sa_t.begin(); it != sa_t.end(); it++)
			{
				track[*it] += 1;
			}
			detector[i] -= 1;

		}
	

	}
	return p;
}



int main()
{
	vector<vector<double>> temp;
	for (int i = 0; i < 4; i++)
	{
		vector<double> t1;
		temp.push_back(t1);
	}

	for (int i = 0; i < 4; i++)
	{
		for (int j = 0; j < 5; j++)
		{
			double t2 = 0;
			temp[i].push_back(t2);
		}
	}
	temp[0][0] = 0.3;
	temp[0][2] = 0.4;
	temp[0][3] = 0.5;
	temp[1][0] = 0.2;
	temp[1][1] = 0.1;
	temp[1][2] = 0.3;
	temp[2][2] = 0.5;
	temp[3][1] = 0.7;
	temp[3][0] = 0.2;
	int *p = KM(temp,0);
	for (int i = 0; i < 5; i++)
	{
		cout << "第" << p[i] << "个点" << "对应"<<i<<"个点"<<endl;
	}
    std::cout << "Hello World!\n";
}

你可能感兴趣的:(算法思考)