poj1182 食物链

/*
  这是我第一次碰到真正意义上,因为cin被卡TLE的情况,甚至取消了cin与stdio的同步,也没有丝毫作用...终于明白大家为什么喜欢用scanf胜过用cin了,以后一定要注意!!!还是用scanf为好
  
  如果仍然被卡,就需要考虑下cout换printf了
*/

#include <iostream>
#include <cstdio> 
using namespace std;
int N, K;
const int MAX_K = 1e5 + 20;
const int MAX_N = 150010;
int T[MAX_K], X[MAX_K], Y[MAX_K];
int par[3 * MAX_N];

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

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

void unite(int x, int y)
{
	int u = find(x);
	int v = find(y);
	
	if (u != v) par[u] = v;
}

bool same(int x, int y)
{
	return find(x) == find(y);
}

void solve()
{
	// 初始化并查集
	// 元素X, X+N, X+2*N分别代表x-A, x-B, x-C
	init(N * 3); 
	
	int ans = 0;
	for (int i = 0; i < K; i++)
	{
		int t = T[i], x = X[i] - 1, y = Y[i] - 1; // 把输入变为0,1,2, N-1的范围
	//	cout << "IN " << i << endl;
		
		// 不正确的编号
		if (x < 0 || x >= N || y < 0 || y >= N)
		{
			ans++; 
		//	cout << "wrong " << i << endl; 
		continue;
		}
		
		if (t == 1) //x和y属于同一类的信息
		{
			if ( same(x, y + N) || same(x, y + 2 * N) ) 
			{
				ans++; 
			//	cout << "wrong " << i << endl;
			}
			else
			{
				unite(x, y);
				unite(x + N, y + N);
				unite(x + 2 * N, y + 2 * N);
			}
		}
		else //x吃y的信息
		{
			if ( same(x, y) || same(x, y + 2 * N) ) 
			{
				ans++;
			//	cout << "wrong " << i << endl;
			}
			else
			{
				unite(x, y + N);
				unite(x + N, y + 2 * N);
				unite(x + 2 * N, y);
			}
		} 
	}
	cout << ans << endl;
}

int main()
{
//	cin.tie(0);
//	cin.sync_with_stdio(false);
//	cin >> N >> K;
	scanf("%d%d", &N, &K);
	for (int i = 0; i < K; i++)
		scanf("%d%d%d", &T[i], &X[i], &Y[i]);
//	cin >> T[i] >> X[i] >> Y[i];
	solve();
	
	return 0;
}

原文地址:https://www.cnblogs.com/mofushaohua/p/7789498.html