您的位置:首页 > 其它

食物链------种类并查集

2017-08-16 16:35 204 查看

原题传送门 :http://poj.org/problem?id=1182

推荐blog传送门,超级详细:http://blog.csdn.net/c0de4fun/article/details/7318642/

这种题,渣渣我是刚不了的……,百度了一堆帖子,说实话谈到关键代码的真的不是很多,也确实有好的帖子,让我收获了不少。

做题思路:

种类并查集,首先利用一个数组a来确定并查集关系,同时在建立一个数组b来表示某点与他们的boss点(根点)的关系。

现规定:

0: 某点与他的根点为同类

1: 某点与他的根点的关系为, 根点种类的动物的可以吃掉该点种类的动物

2: 某点与他的根点的关系为, 该点种类的动物的可以吃掉根点种类的动物

至于 那两个重要公式(代码已标注),如果自己不想推就去看推荐的那个blog,很详细。


4000
点注意:

1.如果两点没有并查集关系,首先给他们确定并查集关系

2. 如果两点有了并查集关系,检验他们所陈述的与根点的关系是否相同

3. 注意 输入的数据大于n的时候 不要让他们进入mergy函数

代码如下

#include <iostream>
#include<cstdio>
#include<cstring>
#include <algorithm>
using namespace std;
int ans;
int a[50100];
int b[50100];
void Init ()//初始化两个数组
{
for(int i=1; i<=50100; i++)
{
a[i]=i;
b[i]=0;
}
}
int get_boss(int x)
{
if(a[x]==x) return x;
else
{
int t=a[x];
a[x]=get_boss(a[x]);
b[x]=(b[x]+b[t])%3;//带权并查集式,重要公式1
return a[x];
}
}

void mergy(int z,int x, int y)
{
int t1=get_boss(x);
int t2=get_boss(y);
if(z==1)
{
if(t1==t2)
{
if(b[x] != b[y])//false
ans++;
}
else
{
a[t2]=t1;
b[t2] = (b[x]-b[y]+3+(z-1))%3;//重要公式2, 另外+3的原因式剪发可能出现负数,因为模3,,3无所谓
}
}
else
{
if(t1==t2)
{
if( (b[x]+1) %3 !=b[y] ) // false // 下述推导
//(b[x]==0 && b[y]==1) || (b[x]==1 && b[y]==2) || (b[x]==2 && b[y]==0),除了这三种都是错的语句
             ans++;
}
else
{
a[t2]=t1;
b[t2] = (b[x]-b[y]+3+(z-1))%3;
}
}
}
int main ()
{
int n,m,x,y,z;
scanf("%d %d",&n,&m);
Init();
ans=0;
while(m--)
{
scanf("%d %d %d",&z,&x,&y);
if(x>n|| y>n) ans++; //false
else if(x==y && z==2) ans++; // false
else  mergy(z,x,y);// n<x, n<y 千万不要让他们进来,错了N遍
}
printf("%d\n",ans);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: