并查集:POJ1182-食物链(并查集比较高端的应用)
2017-07-30 15:46
591 查看
食物链
Time Limit: 1000MS Memory Limit: 10000KDescription
动物王国中有三类动物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 71 101 1
2 1 2
2 2 3
2 3 3
1 1 3
2 3 1
1 5 5
Sample Output
3解题心得:
就是一个很标准的食物链的问题,不懂的可以去看看食物链,其实都是一样的,只不过在poj双面要交,单组输入,写的多组老是wrong。#include<stdio.h> #include<iostream> using namespace std; const int maxn = 1e5+100; struct node { int pre,relation; } p[maxn]; int find(int x) { int temp; if(x == p[x].pre) return x; temp = p[x].pre; p[x].pre = find(temp); p[x].relation = (p[x].relation + p[temp].relation)%3; return p[x].pre; } int main() { int n,m,sum=0; scanf("%d%d",&n,&m); for(int i=0; i<=n; i++) { p[i].pre = i; p[i].relation = 0; } while(m--) { int c,a,b; scanf("%d%d%d",&c,&a,&b); if(a > n || b > n) { sum++; continue; } if(a == b && c == 2) { sum++; continue; } int fa = find(a); int fb = find(b); if(fa != fb) { p[fb].pre = fa; p[fb].relation = (3 + p[a].relation + (c-1) - p[b].relation)%3; } else { if(c == 1 && p[a].relation != p[b].relation) sum++; if(c == 2 && ((3 - p[a].relation + p[b].relation)%3 != c-1)) sum++; } } printf("%d ",sum); return 0; }
在网上看到一份别人的,很简洁的代码:
#include<cstdio> const int N=50001; int p ,r ,n; int findset(int x) { if(x!=p[x]) { int fx=findset(p[x]); r[x]=(r[x]+r[p[x]])%3; p[x]=fx; } return p[x]; } bool Union(int d,int x,int y) { int fx=findset(x),fy=findset(y); if(fx==fy) { if((r[y]-r[x]+3)%3!=d)return 1; else return 0; } p[fy]=fx; r[fy]=(r[x]-r[y]+d+3)%3; return 0; } int main() { int k,ans,i,d,x,y; scanf("%d%d",&n,&k); ans=0; for(i=1;i<=n;i++)p[i]=i,r[i]=0; while(k--) { scanf("%d%d%d",&d,&x,&y); if(x>n||y>n||(x==y&&d==2)){ans++;continue;} if(Union(d-1,x,y))ans++; } printf("%d\n",ans); return 0; }
相关文章推荐
- POJ-1182-食物链- 经典并查集应用
- POJ 1182 食物链【经典并查集应用】
- POJ 1182 食物链【经典并查集应用】
- 并查集应用 —— POJ 1182 食物链
- POJ 1182 食物链(并查集较高级的应用)
- poj 1182 食物链(并查集的综合应用)
- 【解题报告】 POJ 1182 食物链 并查集的经典应用+相对位置
- POJ 1182 食物链【经典并查集应用】
- Hdu 1829 A Bug's Life && Poj 1182 食物链 (并查集偏移量的应用)
- poj1182 食物链 并查集应用
- POJ1182 并查集 食物链 比较难想到 的问题 并查集 中层次 题
- POJ 1182 食物链【经典并查集应用】
- 【POJ1182】 食物链 (带权并查集)
- 带权并查集,经典-食物链,poj-1182
- POJ----1182 食物链[并查集]
- poj 1182 --食物链(经典并查集)
- POJ 1182 食物链(带权并查集)
- POJ-1182 食物链 并查集(互相关联的并查集写法)
- POJ 2912 Rochambeau【并查集经典应用同食物链+枚举】
- poj 1182 食物链 并查集