標籤:mystra 編程演算法 食物鏈 並查集 代碼
食物鏈 並查集 代碼(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)