现在的位置: 首页 > 综合 > 正文

poj 1182 食物链

2013年08月21日 ⁄ 综合 ⁄ 共 1990字 ⁄ 字号 评论关闭

一个并查集的应用,不是把同一类动物并成一类,而是把能够判断其关系的并成一类,其中每个节点都维护一个relat域,表示其和代表元的关系,0表示同一类,1表示其以代表元为食,2表示其被代表元吃,合并时维护该域即可,对于给出的一个句话,先判断这俩个元素是否已经合成一个集合,如果在一个集合中就可以知道它们之前描述的关系了,判断是否与之前描述的关系相辅即可, 如果不在一个集合中,就把这句话当成真的,然后按照其关系合并这俩个集合即可,最后这题不要读入到文件尾,估计数据文件中有其他信息

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <queue>
#include <algorithm>
#include <vector>
#include <cstring>
#include <stack>
#include <cctype>
#include <utility>
#include <map>
#include <string>
#include <climits> 
#include <set>
#include <string> 
#include <sstream>
#include <utility>
#include <ctime>
//#pragma comment(linker, "/STACK:1024000000,1024000000") 

using std::priority_queue;
using std::vector;
using std::swap;
using std::stack;
using std::sort;
using std::max;
using std::min;
using std::pair;
using std::map;
using std::string;
using std::cin;
using std::cout;
using std::set;
using std::queue;
using std::string;
using std::istringstream;
using std::getline;
using std::make_pair;
using std::greater;

//关系: relat[x] = 0表示层 x与fa[x]是同一类
// = 1表示x吃fa[x]
// = 2表示x被fa[x]吃

const int MAXN(50010);

int fa[MAXN], relat[MAXN];

void init(int n)
{
	for(int i = 1; i <= n; ++i)
	{
		fa[i] = i;
		relat[i] = 0;
	}
}

int find(int sour)
{
	if(sour == fa[sour])
		return sour;
	int temp = find(fa[sour]);
	relat[sour] = (relat[sour]+relat[fa[sour]])%3;
	fa[sour] = temp;
	return temp;
}

int change[3] = {0, 2, 1};

void Union(int sour1, int sour2, int flag)  //flag = 0 表示是同一类 = 1表示 sour1吃sour2
{
	int fs1, fs2;
	fs1 = find(sour1);
	fs2 = find(sour2);
	if(fs1 != fs2)
	{
		relat[fs1] = (change[relat[sour1]]+relat[sour2]+flag)%3;
		fa[fs1] = fs2;
	}
}

bool is_legal(int sour1, int sour2, int flag)  //flag = 0表示 sour1 与sour2是同一类, =1 表示sour1吃sour2
{
	int fs1, fs2;
	fs1 = find(sour1);
	fs2 = find(sour2);
	if(fs1 != fs2)
		return true;
	if(flag == 0)
		return relat[sour1] == relat[sour2];
	if((relat[sour1] == 1 && relat[sour2] == 0) ||(relat[sour1] == 2 && relat[sour2] == 1) ||(relat[sour1] == 0 && relat[sour2] == 2))
		return true;
	return false;
}

int main()
{
	int N, K;
	int flag, op1, op2;
	scanf("%d%d", &N, &K);
	init(N);
	int ans = 0;

	for(int i = 1; i <= K; ++i)
	{
		scanf("%d%d%d", &flag, &op1, &op2);
		--flag;
		if(op1 > N || op2 > N)
			++ans;
		else
		{
			if(is_legal(op1, op2, flag))
				Union(op1, op2, flag);
			else
				++ans;
		}
	}
	printf("%d\n", ans);
	return 0;
}

抱歉!评论已关闭.