並查集+虛點 [NOI2001]食物鏈(洛谷 P2024)

[NOI2001]食物鏈

題目描述

動物王國中有三類動物 A,B,C,這三類動物的食物鏈構成了有趣的環形。A 吃 B,B 吃 C,C 吃 A。

現有 N 個動物,以 1 - N 編號。每個動物都是 A,B,C 中的一種,但是我們並不知道它到底是哪一種。

有人用兩種說法對這 N 個動物所構成的食物鏈關係進行描述:

第一種說法是 1 X Y,表示 X 和 Y 是同類。
第二種說法是 2 X Y,表示 X 吃 Y 。

此人對 N 個動物,用上述兩種說法,一句接一句地說出 K 句話,這 K 句話有的是真的,有的是假的。當一句話滿足下列三條之一時,這句話就是假話,否則就是真話。

當前的話與前面的某些真的話衝突,就是假話
當前的話中 X 或 Y 比 N 大,就是假話
當前的話表示 X 吃 X,就是假話
你的任務是根據給定的 N 和 K 句話,輸出假話的總數。


洛谷·P1892 [BOI2003]團伙

P1892 可以說是這題的弱化版,P1892 只涉及了兩個關係,只要弄一個虛點就行,而且最主要的差別是:P1892 朋友的敵人不一定是我的敵人,所以當確定兩個人是朋友關係時,只要把 x 和 y 放在一起,不要涉及 x+n 和 y+n 這兩個虛點;

但是這題就不一樣了,不僅多加一個虛點表示被吃關係,而且當 x 和 y 是同類時(也可以說是朋友),x+n 和 y+n 要關聯在一起,x+2n 和 y+2n 也要關聯在一起,也就是說朋友的敵人一定是我的敵人,朋友的獵物一定是我的獵物;

還有當 x 吃 y 時,不僅要表示 x 和 y 的吃與被吃關係,還要表示 y 的獵物是 x 的天敵這層關係,具體表現就是 x+2n 和 y+n 關聯在一起;

代碼:

#include<bits/stdc++.h>
#define LL long long
#define pa pair<int,int>
#define ls k<<1
#define rs k<<1|1
#define inf 0x3f3f3f3f
using namespace std;
const int N=500100;
const int M=50100;
const int mod=1e9;
int n,k,fa[N];
int find(int p){
	if(p==fa[p]) return p;
	return fa[p]=find(fa[p]);
}
int main(){
	cin>>n>>k;
	for(int i=1;i<=4*n;i++) fa[i]=i;
	int ans=0;
	for(int i=1;i<=k;i++){
		int op,x,y;cin>>op>>x>>y;
		if(x>n||y>n){
			ans++;
			continue;
		}
		if(op==1){
			if(find(x)==find(y+n)||find(x+n)==find(y)) ans++;
			else if(find(x)==find(y+2*n)||find(x+2*n)==find(y)) ans++;
			else{
				fa[find(x)]=find(y);
				fa[find(x+n)]=find(y+n);
				fa[find(x+2*n)]=find(y+2*n);
			}
		} 
		else{
			if(x==y) ans++;
			else{
				if(find(x)==find(y)) ans++;
				else if(find(x)==find(y+n)||find(x+2*n)==find(y)) ans++;
				else{
					fa[find(x)]=find(y+2*n);
					fa[find(y)]=find(x+n);
					fa[find(x+2*n)]=find(y+n);
				}
			}
		}
	}
	cout<<ans<<endl;
	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章