题目描述: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;
x与y属于同类关系说明,如表第一行第一列数据,x1如果和y1是同类的话,那么合并之后,即p[py]=px ;此时px为祖先,跟py的关系为0同类;
第一行第二列数据,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;
}