poj 1182 並查集經典問題
http://poj.org/problem?id=1182
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),輸出假話的總數。
現有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。
以下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
/**
poj 1182 並查集經典問題——食物鏈(一組輸入)
題目大意:給定n個物種,和m個關係1.x和y是同類2.x吃y。問有多少個關係是假話
解題思路:由於n和m很大,所以必須高效的維護動物之間的關係,並快速的判斷是否產生了矛盾。並查集是維護“屬於同一組”的資料結構,但是在本題中,並不只有屬於同一類的
資訊,還有捕食關係的存在,因此需要很好的維護這些關係。對於每隻動物i建立3個元素i-A,i-B,i-C,並用這3*N個元素建立並查集,這個並查集維護如下資訊:
i-x表示:i屬於種類x;
並查集裡的每一個組表示組內所有元素代表的情況都同時發生或不發生。
例如:如果i—A和i-B在同一組裡,就表示如果i屬於種類A那麼j一定屬於種類B,如果j屬於種類B那麼i一定屬於種類A,因此對於每一條資訊,只要按照下面進行操作就可以
了:
第一種:x和y屬於同一類·····合併x-A和y-A、x—B和y—B、x-C和y-C
第二種:x吃y···············合併x-A和y-B、x—B和y-C、x-C和y-A
不過在合併之前要先判斷合併是否會產生矛盾。例如在第一種資訊的情況下,需要檢查比如x-A和y-B或者y-C是否在同一組等資訊。
————摘自《挑戰程式設計競賽》
*/
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <iostream>
using namespace std;
const int maxn=50005;
int p[150010];
int find(int x)
{
return p[x]==x ? x : p[x]=find(p[x]);
}
bool same(int x,int y)
{
return find(x)==find(y);
}
void unite(int x,int y)
{
int u = find(x);
int v = find(y);
if(u != v) p[u] = v;
}
int main()
{
int n,m;
scanf("%d%d",&n,&m);
for(int i=1; i<3*n; i++) p[i] = i;
int ans=0;
while(m--)
{
int id,x,y;
scanf("%d%d%d",&id,&x,&y);
if(x>n||y>n)
{
ans++;
continue;
}
if(id==1)
{
///x and y the same
if(same(x,y+n)||same(x,y+2*n))
{
ans++;
}
else
{
unite(x,y);
unite(x+n,y+n);
unite(x+n*2,y+n*2);
}
}
else
{
/// x eat y
if(same(x,y)||same(x,y+2*n))
{
ans++;
}
else
{
unite(x,y+n);
unite(x+n,y+2*n);
unite(x+2*n,y);
}
}
}
printf("%d\n",ans);
return 0;
}
2015.5.19更新
相關文章
- 【POJ 1182】食物鏈(並查集)並查集
- POJ-1182-食物鏈(並查集種類)並查集
- POJ 1182(食物鏈-另類做法【拆點】)[Template:並查集]並查集
- POJ 1182 食物鏈【擴充套件域 | 邊帶權並查集】套件並查集
- 並查集經典應用場景並查集
- POJ2492(種類並查集)並查集
- 關於並查集問題並查集
- POJ 1308-Is It A Tree?(並查集)並查集
- POJ1797 Heavy Transportation【並查集+貪心】並查集
- POJ 1703-Find them, Catch them(並查集)並查集
- POJ 2492 A Bug's Life(關係並查集)並查集
- POJ 1733 Parity【擴充套件域並查集】套件並查集
- POJ2253 Frogger【並查集+貪心】並查集
- POJ 2492-A Bug's Life(帶權並查集)並查集
- POJ 2236-Wireless Network(並查集)並查集
- POJ 2524-Ubiquitous Religions(入門並查集)UI並查集
- POJ 1703 Find them, Catch them (關係並查集)並查集
- POJ 1611-The Suspects(並查集-同一集合)並查集
- 並查集題目合集並查集
- week2 kuangbin 題單 最短路問題 + 並查集問題並查集
- 面試常考演算法題之並查集問題面試演算法並查集
- 並查集在實際問題中的應用並查集
- 使用並查集處理集合的合併和查詢問題並查集
- 並查集到帶權並查集並查集
- 第二章 :查詢與排序-------遞迴經典問題——漢諾塔問題排序遞迴
- 八數碼 經典問題
- 專題五 並查集【Kuangbin】並查集
- POJ 2492 A bug's life【擴充套件域 | 邊帶權並查集】套件並查集
- 經典的Java面試題及回答集錦Java面試題
- 經典的Java基礎面試題集錦Java面試題
- 【轉】外企英文面試經典考題集錦面試
- 【並查集】【帶偏移的並查集】食物鏈並查集
- SQL language裡面的經典問題SQL
- 揹包問題的一道經典問題
- POJ 2513-Colored Sticks(連線木棍-trie樹+並查集+尤拉通路)並查集
- 樹(tree) - 題解(帶權並查集)並查集
- 並查集(一)並查集的幾種實現並查集
- 3.1並查集並查集