ACM PKU 1182 食物链
题目描述:http://poj.org/problem?id=1182
今天上午闲着没事,把这道题的解题思路仔细梳理一下:
题目是中文的,都看懂了,就不多说了。
对于A、B、C三种动物,他们的关系构成了一个环;如图所示,ABC 直接的关系是吃的关系,有向图:
从三者之间的关系可以看出ABC是轮回对称的,所以只要讨论一个点的关系就够了;
但是对于一个点,仍然存在着三种关系,出了吃别人,和自己被吃之外,还有一个同类型的关系;
对于不能确定两个元素是不是在一个并查集里的情况下,需要进行合并,unionSet()函数来实现;对于X和Y他们的合并需要维护两个数组,一个是并查集的P[]数组,一个是关系数组deff[];
对于x和y,给出一个关系图:
对于同类型,即输入的关系是1的情况,有关系表
同类的关系表 |
Y1 |
Y2 |
Y3 |
X1 |
0 |
2 |
1 |
X2 |
1 |
0 |
2 |
X3 |
2 |
1 |
0 |
x0,x1,x2分别表示x与px的关系为,x为px的同类,px吃x,x吃px;
第一行第二列数据,x1如果和y2是同类的话,那么合并之后,即p[py]=px ;此时px为祖先,跟py的关系为2,表示py会吃px;
第一行第三列数据,x1如果和y3是同类的话,那么合并之后,即p[py]=px ;此时px为祖先,跟py的关系为1,表示px会吃py;
可以的出关系公式为deff[py]=(x-y+3)%3;
对于吃的关系同样可以画出关系表
同类的关系表 |
Y1 |
Y2 |
Y3 |
X1 |
1 |
0 |
2 |
X2 |
2 |
1 |
0 |
X3 |
0 |
2 |
1 |
说明就不写了,自己慢慢推吧,最后的公式是deff[py]=(x-y+4)%3;
附上代码:
#include <iostream> #include <cstring> #include <cstdio> using namespace std; const int MAXN=50000; int p[MAXN+10],d[MAXN]; int N,K,ans; void init() { for(int i=1; i<=N; i++) { p[i]=i; d[i]=0; } } int find(int x) { if(p[x]==x)return x; int px=find(p[x]); d[x]=(d[x]+d[p[x]])%3; return p[x]=px; } bool unionSet(int x,int y,int D) { int px=find(x);int py=find(y); if(px==py)return((d[x]-d[y]+D-1)%3!=0); p[py]=px; d[py]=(d[x]-d[y]+D+2)%3; return false; } int main() { freopen("in.txt","r",stdin); ans=0; scanf("%d%d",&N,&K); init(); for(int i=0,D,x,y; i<K; i++) { scanf("%d%d%d",&D,&x,&y); if(x>N || y>N || (x==y && D==2)) { ans++; continue; } else ans+=unionSet(x,y,D); } printf("%d\n",ans); return 0; }