首页 > 代码库 > 编程算法 - 食物链 并查集 代码(C)

编程算法 - 食物链 并查集 代码(C)

食物链 并查集 代码(C)


本文地址: http://blog.csdn.net/caroline_wendy


题目: 有N只动物, 分别编号为1,2,...,N. 所有动物都属于A,B,C中的一种. 已知A吃B, B吃C, C吃A.

按顺序给出两种信息K条.

第一种: x和y属于同一类.

第二种: x吃y. 

信息之间可能会出错和矛盾, 求不正确的信息数.


例如:

有N=10只动物, 给定K=7条信息.

(1) 1: x=101, y=1; 出错:没有101的动物.

(2) 2: x=1, y=2; 动物1吃动物2.

(3) 2: x=2, y=3; 动物2吃动物3.

(4) 2: x=3, y=3; 出错, 动物3不能吃动物3.

(5) 1: x=1, y=3; 出错, 动物1和动物3属于同一种, 与(2)(3)矛盾.

(6) 2: x=3, y=1; 动物3吃动物1.

(7) 1: x=5, y=5; 动物5和动物5属于同一种.

result = 3, 即(1)(4)(5)出错.


使用并查集(disjoint set)求解.

创建3*N个元素的并查集.每一组表示元素i可能属于的种类x, 共3种.

然后合并并查集. 找到矛盾信息.


代码:

/*
 * main.cpp
 *
 *  Created on: 2014.7.20
 *      Author: Spike
 */

/*eclipse cdt, gcc 4.8.1*/

#include <stdio.h>

/*
 * main.cpp
 *
 *  Created on: 2014.7.20
 *      Author: spike
 */

/*eclipse cdt, gcc 4.8.1*/

#include <stdio.h>
#include <memory.h>
#include <limits.h>

#include <algorithm>

using namespace std;

class DisjoinSet {
	static const int MAX_N = 10000;
	int par[MAX_N];
	int rank[MAX_N];
public:
	void init(int n) {
		for (int i=0; i<n; i++) {
			par[i] = i;
			rank[i] = 0;
		}
	}
	int find (int x) {
		if(par[x] == x) {
			return x;
		} else {
			return par[x] = find(par[x]);
		}
	}
	void unite(int x, int y) {
		x = find(x);
		y = find(y);
		if (x == y) return;
		if (rank[x] < rank[y]) {
			par[x] = y;
		} else {
			par[y] = x;
			if (rank[x] == rank[y]) rank[x]++;
		}
	}
	bool same(int x, int y) {
		return find(x) == find(y);
	}
};

class Program {
	static const int MAX_N = 100;
	int N = 100, K = 7;
	int T[MAX_N] = {1,   2, 2, 2, 1, 2, 1},
		X[MAX_N] = {101, 1, 2, 3, 1, 3, 4},
		Y[MAX_N] = {1,   2, 3, 3, 3, 1, 4};
	DisjoinSet DS;
public:
	void solve() {
		DS.init(N*3);
		int ans = 0;
		for (int i=0; i<K; i++) {
			int t = T[i];
			int x = X[i]-1, y = Y[i]-1;

			if (x<0 || N<=x || y<0 || N<=y) {
				ans ++;
				continue;
			}

			if (t==1) {
				if (DS.same(x, y+N) || DS.same(x, y+2*N)) {
					ans++;
				} else {
					DS.unite(x, y);
					DS.unite(x+N, y+N);
					DS.unite(x+N*2, y+N*2);
				}
			} else {
				 if (DS.same(x,y) || DS.same(x, y+2*N)) {
					 ans++;
				 } else {
					 DS.unite(x, y+N);
					 DS.unite(x+N, y+2*N);
					 DS.unite(x+2*N, y);
				 }
			}
		}

		printf("ans = %d\n", ans);
	}

};

int main(void)
{
	Program iP;
	iP.solve();

	return 0;
}


输出:

ans = 3







编程算法 - 食物链 并查集 代码(C)