POJ1182-并查集
2012-08-14 17:39
176 查看
这题有一个关键点: x的食物的食物以x为食,即生物间的关系是以3为循环的,就像运算 (0+1)%3=1,(1+1)%3=2,(2+1)%3=0,(0+1)%3=1... ...
不管d=1还是d=2,都表示x与y有关系,因此可以并到一个并查集里去,然而具体的同类与捕食关系可用0,1,2来代表;
这里以r[i]表示i与其并查集中父节点p[i]的关系: 0表示同类,1表示i吃p[i],2表是i被p[i]吃;
那么如果x和y在同一个并查集时,可通过查询x与根节点的关系,y与根节点的关系来判断x与y的关系。若在并查集的find操作中压缩路径的话,根节点也就成了父节点,好方便!
另外合并和查找时可以利用一些加法,对3取模的运算来更新r。
AC代码:
不管d=1还是d=2,都表示x与y有关系,因此可以并到一个并查集里去,然而具体的同类与捕食关系可用0,1,2来代表;
这里以r[i]表示i与其并查集中父节点p[i]的关系: 0表示同类,1表示i吃p[i],2表是i被p[i]吃;
那么如果x和y在同一个并查集时,可通过查询x与根节点的关系,y与根节点的关系来判断x与y的关系。若在并查集的find操作中压缩路径的话,根节点也就成了父节点,好方便!
另外合并和查找时可以利用一些加法,对3取模的运算来更新r。
AC代码:
#include <cstdio> #include <cstring> #include <iostream> using namespace std; const int NN=50005; int n; int p[NN]; //根节点 int r[NN]; //与父节点的关系,0:同类,1:吃根节点,2:被根节点吃 inline void get(int &x) { char c=getchar(); while (c<'0' || c>'9') c=getchar(); x=c-'0'; c=getchar(); while (c>='0' && c<='9') x=x*10+c-'0',c=getchar(); } int find(int x) { if (p[x]!=x) { int t=p[x]; p[x]=find(p[x]); r[x]=(r[x]+r[t])%3; //x与新父节点(根节点)的关系 } return p[x]; } int Union(int d,int x,int y) { int fx=find(x); int fy=find(y); p[fx]=fy; r[fx]=(r[y]-r[x]+2+d)%3; //fx与fy的关系=y与fy的关系和x与fx的关系差+x与y的关系 } int main() { int d,x,y,k,cnt=0; scanf("%d%d",&n,&k); for (int i=1; i<=n; i++) { p[i]=i; r[i]=0; } while (k--) { get(d); get(x); get(y); if (x>n || y>n) cnt++; else if (d==2 && x==y) cnt++; else if (find(x)!=find(y)) Union(d,x,y); else if ((r[y]+d+2)%3!=r[x]) cnt++;//这句话一定是在find(x)和find(y)之后的,因为find过后r[x]才是x与其根节点的关系 } printf("%d\n",cnt); return 0; }
相关文章推荐
- POJ1182并查集的应用
- POJ - 1182 食物链(并查集)
- poj 1182 食物链(并查集)
- poj 1182 食物链 带权并查集
- poj 1182 食物链 并查集
- poj1182 种类并查集
- poj 1182:食物链(种类并查集,食物链问题)
- POJ 1182 食物链 并查集
- poj 1182(食物链)并查集
- poj 1182 食物链---带权值的并查集
- poj1182----带权并查集的应用
- 并查集:POJ 1182 食物链 复习
- POJ 1182 食物链(带权并查集)
- POJ1182 食物链(并查集)
- POJ 1182 食物链——种类并查集
- 【并查集】poj 1182 食物链
- POJ 1182 食物链 【并查集】
- G/A - 食物链 POJ - 1182(并查集)
- poj 1182(并查集的边权向量关系)
- POJ 1182食物链(经典并查集算法改进)