标签:oid 回车 遍历 自己 表示 log etc 换行 bool
加权并查集是一种特殊的并查集,除可提供查询操作外,还可用于表示元素与其代表元素的关系。下面以食物链为例,讲解一下加权并查集。
#include<cstdio> //调用cstdio库,使用getchar函数
#include<cctype> //调用cctype库,使用isdigit函数,返回参数是否为整数
int N,K,ans,r,x,y; //定义变量用于有几个动物,几句话,答案,以及动物的关系和两个要描述的动物
int f[50005],d[50005]; //定义数组记录代表元素,以及到达代表元素的距离
inline int get_num() { //内联get_num函数,读入整数
int num = 0; //定义整型变量num,并赋值为0
char c; //定义字符型变量c
bool flag = false; //定义布尔值变量flag,并置为假
while ((c = getchar()) == ‘ ‘ || c == ‘\n‘ || c == ‘\r‘); //忽略开头的空格,换行符及回车符
if (c == ‘-‘) flag = true; //如果读到负号,就将负数标志置为真
else num = c - ‘0‘; //否则将读到的第一个数字保存;
while (isdigit(c = getchar())) //只要读入的还是数字,就循环
num = num * 10 + c - ‘0‘; //将num整体前移一位,并将新读入的一位数字保存
return (flag ? -1 : 1) * num; //返回读到的整数,若负数标志为真,就返回其相反数,即一个负数
}
int find(int i) { //定义函数查询代表元素以及到达代表元素的距离
if(i==f[i]) return i; //找到代表元素返回
int oldf=f[i]; //记录下元素之前的代表元素
f[i]=find(f[i]); //更新元素的代表元素
d[i]=(d[i]+d[oldf])%3; //更新元素与代表元素的距离
return f[i]; //返回代表元素
}
void check(int r,int x,int y) { //定义函数检查是否为假话
if(x>N||y>N) {++ans;return;} //若动物编号超出范围,则为假话
if(r==2&&x==y) {++ans;return;} //若说动物自己吃自己,则为假话
if(find(x)==find(y)) { //若两个动物在同一集合中
if((d[x]-d[y]+3)%3!=r-1) ++ans;return; //动物之间的距离不符合描述,则为假话
}
else {
d[f[x]]=(3-d[x])%3; //求出代表元素到该元素的距离
f[f[x]]=x;f[x]=y; //让代表元素指向该元素,即该元素成为代表元素,并指向y
d[f[y]]=(3-d[y])%3; //同上
f[f[y]]=y;f[y]=y;d[y]=0; // 同上,并让y成为代表元素,令其到代表元素的距离为0
if(r==1) d[x]=0; //若为同类,则x到y距离为0
else d[x]=1; //若x吃y,则x到y距离为1
/* 另一种合并方法
f[f[y]]=f[x]; //让y的代表元素指向x的代表元素
d[f[y]]=(d[x]-d[y]-(r-1)+3)%3; //更新y的代表元素到其代表元素的距离
*/
}
}
int main() {
N=read();K=read(); //读入N,K
for(int t=1;t<=N;++t) f[t]=t; //初始化每个元素的代表元素
for(int t=1;t<=K;++t) { //遍历每句话
r=read();x=read();y=read(); //读入r,x,y
check(r,x,y); //调用check函数
}
printf("%d",ans); //打印答案
return 0;
}
标签:oid 回车 遍历 自己 表示 log etc 换行 bool
原文地址:http://www.cnblogs.com/Mr94Kevin/p/7577102.html