食物鏈(並查集的簡單應用)
題目來源:[NWPU][2014][TRN][12]並查集 C 題
http://vjudge.net/contest/view.action?cid=50731#problem/C
作者:npufz
題目:
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
程式碼:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
using namespace std;
int parent[50003];
int real[50003],n;
int getparent(int a)
{
if(a==parent[a])
return a;
int t;
t=getparent(parent[a]);
real[a]=(real[parent[a]]+real[a])%3;
//cout<<real[a]<<endl;
parent[a]=t;
return parent[a];
}
bool panduan (int d,int dw1,int dw2)
{
int pre1,pre2;
if(dw1>n||dw2>n||dw1<1||dw2<1||d>2||d<1) return false ;
if(d==2&&dw1==dw2) return false;
if(d==1&&dw1==dw2) return true;
pre1=getparent(dw1);
pre2=getparent(dw2);
if(d==1)
{
if(dw1==dw2) return true;
if(dw1!=dw2)
{
if(pre1==pre2)
{
if(real[dw1]==real[dw2]) return true;
return false;
}
if(pre1!=pre2)
{
if(real[dw1]>=real[dw2])
{
parent[pre2]=pre1;
real[pre2]=(real[dw1]-real[dw2]);
return true;
}
else
{
parent[pre1]=pre2;
real[pre1]=(real[dw2]-real[dw1]);
return true;
}
}
}
}
if(d==2)
{
if(pre1==pre2)
{
if((real[dw2]-real[dw1])==1) return true;
if((real[dw1]-real[dw2]==2)) return true;
return false ;
}
if(pre1!=pre2)
{
if(real[dw1]==real[dw2])
{
parent[pre2]=pre1;
real[pre2]=1;
return true;
}
if((real[dw1]+1)>=real[dw2])
{
//cout<<"ok"<<real[pre2]<<endl;
parent[pre2]=pre1;
real[pre2]=((real[dw1]+1)-real[dw2])%3;
//cout<<"ok"<<real[pre2]<<endl;
return true;
}
if((real[dw1]+1)<real[dw2])
{ //cout<<"not ok"<<real[pre2];
parent[pre2]=pre1;
real[pre2]=2;
//cout<<"not ok"<<real[pre2];
return true;
}
}
}
return true;
}
int main()
{
int k,d,dw1,dw2,wrong;
scanf("%d%d",&n,&k);
for(int i=1;i<=n;i++)
{
real[i]=0;
parent[i]=i;
}
wrong=0;
for(int i=0;i<k;i++)
{
scanf("%d%d%d",&d,&dw1,&dw2);
if(!panduan(d,dw1,dw2))
wrong++;
}
printf("%d\n",wrong);
return 0;
}
反思:並查集在於把元素的分類和關係的描述上進行合理的資料維護,用壓縮路徑或者是RANK值使複雜度控制在LOG N 以下,具體的實現形式不拘一格,在這一題中,我把動 物之間已知的關係構造出一顆顆的樹,也就是森林,當兩棵樹的元素有關係時,就把一棵樹的樹根連到另一棵樹根上,在每次進行對樹根的查詢時,就直接把這個葉子節 點連線到根節點上,並同時確定它和根節點的關係,一開始由於第81行的那個是2的值寫成了1,就WA了,還以為整個資料集合的處理有問題,就糾結了一個晚上也沒有
找出錯誤,後來找到就A了相關文章
- 食物鏈(並查集)並查集
- 【並查集】【帶偏移的並查集】食物鏈並查集
- 並查集的簡單應用並查集
- 【POJ 1182】食物鏈(並查集)並查集
- hdu 1829 並查集(食物鏈的弱化版)並查集
- POJ-1182-食物鏈(並查集種類)並查集
- 並查集的應用並查集
- 並查集應用並查集
- 並查集—應用並查集
- POJ 1182(食物鏈-另類做法【拆點】)[Template:並查集]並查集
- 並查集的應用2並查集
- 並查集深度應用並查集
- 並查集以及應用並查集
- POJ 1182 食物鏈【擴充套件域 | 邊帶權並查集】套件並查集
- 並查集的分析及應用並查集
- 並查集(二)並查集的演算法應用案例上並查集演算法
- 並查集應用總結並查集
- 簡單易懂的並查集演算法以及並查集實戰演練並查集演算法
- 並查集的應用:hdu 1213並查集
- 社交網路 (並查集的應用)並查集
- 並查集詳解與應用並查集
- 並查集擴充套件應用並查集套件
- HDU 1272小希的迷宮(簡單並查集)並查集
- 並查集經典應用場景並查集
- 【學習筆記】並查集應用筆記並查集
- 並查集的初級應用及進階並查集
- 並查集(Union-Find) 應用舉例並查集
- 【帶權並查集】理論和應用並查集
- 並查集 (Union-Find Sets)及其應用並查集
- 並查集在實際問題中的應用並查集
- 資料結構 — 並查集的原理與應用資料結構並查集
- 食物鏈
- 並查集到帶權並查集並查集
- 並查集(一)並查集的幾種實現並查集
- 【演算法】並查集的運用演算法並查集
- 舌尖上的AI:食物產業鏈的人工智慧應用報告AI產業人工智慧
- 並查集(Union-Find) 應用舉例 --- 基礎篇並查集
- 資料結構之Kruskal演算法(並查集的應用)資料結構演算法並查集