最近学算法学到并查集,感觉挺简单的。于是乎在poj里找相关的题目练练手,一做就懵了。即便知道这道题是用到什么数据结构去做,可是把一个实际问题抽象转化为学过的数据结构与算法的过程也还挺难的。然后参考别人的解题报告写出来了poj1182题。
总结并查集的用法如下:
一般来说,给定的问题都不可能像书本上的例子那样,直接让你求一些元素的并集,而是给定一些元素,其中某些元素发生关系(这个关系可以有很多种),然后让你得出更多的这些元素之间的关系。
struct Node
{
int parent;//父节点
E relation; //当前结点与父结点的关系
};
union( )//某些元素发生关系时,更新并查集(即更新某些元素的parent和relation)
find()//查找某个元素的父节点 为了压缩路径,往往这里要进行一些附带的操作,更新经过的路径上的结点,使他们能更快地到达父节点
poj 1182 食物链
代码:
#include<iostream>
#include<fstream>
#include<time.h>
using namespace std;
struct Node
{
int parent;
int relation;
};
Node *UFSet;
int getParent(int x)
{
int temp_p;
if(UFSet[x].parent!=x)
{
temp_p=UFSet[x].parent;
UFSet[x].parent=getParent(temp_p);
UFSet[x].relation=(UFSet[x].relation+UFSet[temp_p].relation)%3;
}
return UFSet[x].parent;
}
void Union(int x,int y,int r1,int r2,int rel)
{
UFSet[r1].parent=r2;
UFSet[r1].relation=(UFSet[y].relation-UFSet[x].relation+2+rel)%3;
}
int main()
{
freopen("input.txt","r",stdin);
int N,K;
scanf("%d",&N);
UFSet=new Node[N+1];
int error_num=0;
for(int i=1;i<=N;i++)
{
UFSet[i].parent=i;
UFSet[i].relation=0;
}
scanf("%d",&K);
int rel,x,y;
for(int i=0;i<K;i++)
{
scanf("%d%d%d",&rel,&x,&y);
if(x>N||y>N)
{
error_num++;
continue;
}
if(x==y&&rel==2)
{
error_num++;
continue;
}
int r1=getParent(x);
int r2=getParent(y);
if(r1!=r2)
{
Union(x,y,r1,r2,rel);
}
else
{
if((UFSet[y].relation+rel+2)%3!=UFSet[x].relation)
error_num++;
}
}
printf("%d\n",error_num);
return 0;
}
这个题的输入较多,C++的同学也最好用scanf。