POJ 1182(食物鏈-另類做法【拆點】)[Template:並查集]

weixin_34391854發表於2015-02-20

食物鏈
Time Limit: 1000MS   Memory Limit: 10000K
Total Submissions: 46039   Accepted: 13400

Description

動物王國中有三類動物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句話有的是真的,有的是假的。當一句話滿足下列三條之中的一個時,這句話就是假話,否則就是真話。 
1) 當前的話與前面的某些真的話衝突,就是假話; 
2) 當前的話中X或Y比N大,就是假話; 
3) 當前的話表示X吃X,就是假話。 
你的任務是依據給定的N(1 <= N <= 50,000)和K句話(0 <= K <= 100,000),輸出假話的總數。 

Input

第一行是兩個整數N和K,以一個空格分隔。 
下面K行每行是三個正整數 D,X,Y,兩數之間用一個空格隔開,當中D表示說法的種類。 
若D=1,則表示X和Y是同類。 
若D=2,則表示X吃Y。

Output

僅僅有一個整數,表示假話的數目。

Sample Input

100 7
1 101 1 
2 1 2
2 2 3 
2 3 3 
1 1 3 
2 3 1 
1 5 5

Sample Output

3

Source


i-A,i-B,I-C :表示i在第(A,B,C)類。

同一組:表示若1個組員成立,組員全成立


則可分別維護i在A,B,C組的情況。

i,j 同類:i-A=j-A,i-B=j-B,I-C=j-C

i吃j      :i-A=j-B,i-B=j-C,I-C=j-A

推斷   :若i-A和j-B同類,則必有i吃j,否則無法確定(或因為其他連線不可能實現)。以此類推。


#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<functional>
#include<iostream>
#include<cmath>
#include<cctype>
#include<ctime>
using namespace std;
#define For(i,n) for(int i=1;i<=n;i++)
#define Fork(i,k,n) for(int i=k;i<=n;i++)
#define Rep(i,n) for(int i=0;i<n;i++)
#define ForD(i,n) for(int i=n;i;i--)
#define RepD(i,n) for(int i=n;i>=0;i--)
#define Forp(x) for(int p=pre[x];p;p=next[p])
#define Lson (x<<1)
#define Rson ((x<<1)+1)
#define MEM(a) memset(a,0,sizeof(a));
#define MEMI(a) memset(a,127,sizeof(a));
#define MEMi(a) memset(a,128,sizeof(a));
#define INF (2139062143)
#define F (100000007)
#define MAXN (3*50000+10)
#define MAXM (100000+10)

long long mul(long long a,long long b){return (a*b)%F;}
long long add(long long a,long long b){return (a+b)%F;}
long long sub(long long a,long long b){return (a-b+(a-b)/F*F+F)%F;}
typedef long long ll;
class bingchaji
{
public:
	int father[MAXN],n;
	void mem(int _n)
	{
		n=_n;
		For(i,n) father[i]=i;
	}
	int getfather(int x) 
	{
		if (father[x]==x) return x;
		
		return father[x]=getfather(father[x]);
	}
	void unite(int x,int y)
	{
		father[x]=getfather(father[x]);
		father[y]=getfather(father[y]);
		father[father[x]]=father[father[y]];
	}
	bool same(int x,int y)
	{
		return getfather(x)==getfather(y);
	}
}S;

int main()
{
//	freopen("poj1182_template.in","r",stdin);
//	freopen(".out","w",stdout);
	int n,m;
	scanf("%d%d",&n,&m);
	S.mem(n*3);
	int ans=0;
	For(i,m)
	{
		int d,x,y;
		scanf("%d%d%d",&d,&x,&y);
		if (x>n||y>n||x<1||y<1) {ans++;continue;}
		if (d==1) 
		{
			if (S.same(x,y+n)||S.same(x,y+2*n)) ans++;
			else 
			{
				S.unite(x,y);S.unite(x+n,y+n);S.unite(x+2*n,y+2*n);
			}
		}
		else
		{
			if (S.same(x,y)||S.same(x,y+2*n)) ans++;
			else 
			{
				S.unite(x,y+n);S.unite(x+n,y+2*n);S.unite(x+2*n,y);
			}
			
		}
	}
	cout<<ans<<endl;
	
	return 0;
}



相關文章