POJ 1703 Find them, Catch them 种类并查集

来源:互联网 发布:广电网络整合最新消息 编辑:程序博客网 时间:2024/05/22 15:28

题意

给出一堆点和关系
D为两点不同集合
A为查询两点是否不同集合
n<=1e5

code

#include<cstdio>#include<iostream>#include<algorithm>using namespace std;const int maxn = 1e5+7;int f[maxn],rel[maxn];//rel为0表示与父节点不同类 1为同类int find(int x){    int t;    if(f[x]==x)return x;    t = find(f[x]);    rel[x] = (rel[x]+rel[f[x]]+1)%2;//当前节点与旧父节点之间的关系、父节点与根节点的关系 可以判断出 当前节点和根节点的关系 即所谓的关系运算 模拟现实中的关系判断     return f[x] = t;//如果这里面总是保存的与父节点的关系 我们没法通过两个不同的节点判断他俩的关系 但我们如果知道两个不同的节点与根节点的关系 就可以判断两个节点之间的关系 }//当我们需要判断两个点的关系时 我们需要知道两个节点对一个相同的节点的关系 才能判断出当前两个节点的关系 int main(){    int t;    scanf("%d",&t);    while(t--){        int n,m;        scanf("%d%d",&n,&m);        for(int i=1;i<=n;i++)        f[i] = i,rel[i] = 1;        while(m--){            char o[4];            int a,b;            scanf("%s%d%d",o,&a,&b);            int fa = find(a);            int fb = find(b);            if(o[0]=='A'){                if(fa==fb){                    if(rel[a]==rel[b])puts("In the same gang.");                    else puts("In different gangs.");//与根节点关系不同 那么一定不同集                 }                 else puts("Not sure yet.");            }            else {//只要有关系 就给他们连到一起 不管什么关系 我们都可以用rel数组记录他们分别于根节点的关系 那么我们如何判断这两个点的关系 就可以通过他们分别对根节点的关系来做出来                 f[fa] = fb;                rel[fa] = (rel[a]+rel[b])%2;            }        }    }    return 0;}

分析

种类并查集
当我们判断两个点的关系时 我们如何判断呢
基础的并查集知识告诉我们 我们可以判断这两个点是否在一个联通块中 这两个点是否是一个集合
现在关系复杂了 两个元素可以是一个集合的也可以是不同集合的 我们如何判断呢
假设我们记录下每个节点与父节点的关系
那么当我们查询两个节点时
我们都知道他们与父节点的关系
我们也知道他们的根节点是谁
if 两个节点是不同集合的 那么我们如何判断出来呢

仅凭两个父节点貌似不好判断
假如每一个关系都建立一个独立的树
由于数据并不是按照相同关系给我们的
而是按照不同或相同关系给我们的
那么我们就需要递推两个元素的关系
假如 a-b不同 b-c不同 那么a-c相同 我们需要判断出来
这里就需要种类并查集来做
假如当我们查询 ac的关系的时候 如果我们都知道 a和c与另外一个节点的关系
那么我们就能判断出来ac的关系 通过两个变量与共同的第三方变量的关系
于是种类并查集规定
我们维护每个点和父节点的关系 但最终我们实质维护的是每个节点与 根节点的关系!
假如所有出现的两个点都在一棵树里 没出现的点 我们不必管
我们只需要去维护每个点与根节点的关系 我们就可以推出两个节点的相互关系
如何实现这个关系 就是利用关系数量取余操作
因为这里的关系 并不是每个集合一个独立的树 独立的树 我们无法判断交叉关系假如 a在一个树上 b在另一颗树上 那么c如何连到与b不同的那棵树呢?可以维护两个集合 只不过有些时候我们的关系不止是两层 有时关系会变成多层 那么就不好维护两个集合了

话说种类并查集有没有迭代的写法?

原创粉丝点击