拓扑排序判断环

hdoj 1811 Rank of Tetris

由于有等号的情况,所以要运用并查集,具有相等的点都有公共的父节点,从而相等的化作一个点。

然后拓扑排序判断有没有环。

#include <iostream>
#include <vector>
#include <algorithm>
#include <queue>
using namespace std;

struct Node {
	int a, b;
}ns[20005];

int bc[10005];

int N, M, cnt;
int in[10005];
vector<int> vec[10005];

int find(int x) { return bc[x] == x ? x : find(bc[x]) ; } 

void merge(int a, int b) {
	a = find(a); b = find(b);
	a > b ? bc[a] = b : bc[b] = a;
}


void init() {
	int i, a, b, finda, findb;
	char str[5];
	cnt = 0;
	for(i=0; i<=10000; ++i) {
		bc[i] = i;
		in[i] = 0;
		vec[i].clear();
	}
	
	for(i=0; i<M; ++i) {
		scanf("%d %s %d", &a, str, &b);
		switch(str[0]) {
		case '=' : merge(a, b); break;
		case '>' : ns[cnt].a = a; ns[cnt++].b = b; break;
		case '<' : ns[cnt].a = b; ns[cnt++].b = a; break;		
		}
	}

	for(i=0; i<cnt; ++i) {
		finda = find(ns[i].a);
		findb = find(ns[i].b);
		in[findb] ++;
		vec[finda].push_back(findb);
	}
}


int solve() {
	int i, j, finda, findb;
	int ans = 0, count = 0, c = 0;
	queue<int> Q;

	for(i=0; i<N; ++i) {
		if(bc[i]!= i) continue;
		count ++;
		if(in[i] == 0) Q.push(i);
	}

	while(Q.size()) {
		if(Q.size() > 1) ans = 1;
		finda = Q.front();
		Q.pop();
		c ++;
		for(i=0; i<vec[finda].size(); ++i) {
			findb = vec[finda][i];
			in[findb] --;
			if(in[findb] == 0) Q.push(findb);
		}
	}

	if(c < count) ans = -1; //表面有环
	return ans;
}			


int main() {
//	freopen("c:/aaa.txt", "r", stdin);
	while(scanf("%d %d", &N, &M) == 2) {
		init();
		switch(solve()) {
			case -1:puts("CONFLICT");break;   
			case 1:puts("UNCERTAIN");break;   
			case 0:puts("OK");   
        }   

	}
	return 0;
}

posted on 2011-02-17 13:25  CrazyAC  阅读(1473)  评论(0)    收藏  举报