POJ1703并查集(区分两个集合)

    

    题意:输入n,m。n个人,m个规定/询问。一共有两个集合,A:询问a,b是否在同一个集合?D:表明a,b不在同一个集合。输出有三种,不在同一集合,在同一集合,不确定。

    解析:其实有点离散化的意思。传统并查集是合并两个集合,而这个题是分开两个集合。那么可以这么做,想办法进行合并操作。输入a,b,a,b没有了关系,但是可以规定,a+n,b属同一集合,a,b+n属于同一集合。即,n右边a+n的那些和b放入同一集合,n右边b+n的那些和a放入同一集合,这样a,b就撇开了关系。就可以进行join()操作了。判断过程具体看代码吧。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<map>
using namespace std;
typedef long long ll;
const int maxn=2e5+1000;
int pr[maxn];
//int vis[maxn];
int sum=0;
int n,m;
int find(int x){
    while(x!=pr[x])
    {
        pr[x]=pr[pr[x]];
        x=pr[x];
    }
    return x;
}
void join(int x1,int x2)
{
    int f1=find(x1),f2=find(x2);
    if(f1!=f2)
    {
        pr[f1]=f2;
    }
    return ;
}
void first()
{
    for(int i=0;i<=n*2+10;i++)
    {
        pr[i]=i;
    }
}
bool check(int a,int b)
{
    int f1=find(a),f2=find(b);
//    cout<<f1<<"-"<<f2<<endl;
    if(f1==f2)
    {
        return true;
    }
    return false;
}
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d%d",&n,&m);
        first();
        char ch,ch2;
        while(m--)
        {

        //    cin>>ch;
            int x,y;
            scanf("%c",&ch);
            scanf("%c%d%d",&ch,&x,&y);
            if(ch==‘D‘)
            {
                join(x+n,y);
                join(x,y+n);
            }
            else
            {
                if(check(x,y)||check(x+n,y+n))  //如果x+n,x+n属于同一个集合,那么a,b之前肯定记录过而且同属一个集合。
                    cout<<"In the same gang."<<endl;  
                else if(check(x+n,y)||check(y+n,x))  //如果x+n和y同属一个集合或者y+n和x同属一个集合,那么x,y肯定同属一个集合了。
                    cout<<"In different gangs."<<endl;
                else                   
                    cout<<"Not sure yet."<<endl;  //否则就不确定
            }
        }
    }
}

  

原文地址:https://www.cnblogs.com/liyexin/p/12530816.html

时间: 2024-12-09 18:49:29

POJ1703并查集(区分两个集合)的相关文章

可持久化并查集的两种实现

对于像UVA 11987 Almost Union-Find这样的题目,要求把一个元素从一个集合中剥离的情况,我们只需要新建一个节点然后---. 还是看代码吧: inline void move(int x,int y) // 把x从y集合中剥离 { int fx = find(id[x]),fy = find(id[y]); if(fx == fy) return ; cnt[fx] --,sum[fx] -= x; id[x] = ++ tot; // 可持久化 f[id[x]] = fy;

poj1703并查集

直接搞. #include <cstdio> #include <cstring> #include <algorithm> #include <climits> #include <string> #include <iostream> #include <map> #include <cstdlib> #include <list> #include <set> #include &

Find them, Catch them.(POJ-1703)(并查集)

本题也是一道经典的并查集题目,只不过并不是直来直去的,因为需要维护两组关系:同一伙.不是同一伙. 那要怎么办呢,一开始我用了vector来保存对立面,建立两个并查集,结果很自然是超时的,因为循环了太多次. 之后看别人的题解,感觉有点复杂,看的不是很明白,只有一篇给出了一个简单的方法,然后我又重新看了食物链那道题,发现本题就是那道题的改编,可以使用相同的方法来维护多组关系. 就像食物链那道题一样,对每个人创建两个元素:i和i+n.用3*n个元素来建立并查集,这个并查集可以维护如下信息: 如果x和y

并查集的两种实现(按秩合并+路径压缩)

并查集:就是有求并集,查找元素属于哪个集合的功能. 1.路径压缩:使X到根上的每一个节点的父节点都变为根节点. 查询: void Find(int x) { if(a[x]==0) return x; else return a[x]=Find(a[x]); } 合并: void Merge(int x,int y) { int t1=Find(x),t2=Find(y); if(t1!=t2) a[t1]=t2; } 2.按秩合并:使较浅的树成为较深的树的子树. 查询: void Find(i

食物链 POJ - 1182 (并查集的两种写法)

这是一个非常经典的带权并查集,有两种写法. 1 边权并查集 规定一下,当x和y这条边的权值为0时,表示x和y是同类,当为1时,表示x吃y,当为2时,表示x被y吃. 一共有三种状态,如图,当A吃B,B吃C时,C必须吃A,路径压缩后,A被C吃. 然后就是带权并查集的模板了. 判断条件,当x和y在同一颗树上是, 如果说,x和y之间的关系是0,那么x和RA与Y和RA之间的关系必须相同才行.x和Y之间的关系是1,当S[y]=2时,S[x]=1,当s[y]=1时,s[x]应等于0,才能满足 所以判断条件为(

BNUOJ33566 Cycling Roads(并查集+判断两线段相交)

Cycling Roads Time Limit: 1000ms Memory Limit: 65536KB This problem will be judged on Ural. Original ID: 1966 64-bit integer IO format: %lld      Java class name: (Any) Prev Submit Status Statistics Discuss Next Font Size:  +   - Type:   None Graph T

并查集的两个优化(秩优化+路径压缩)

路径压缩 寻找祖先时采用递归,但是一旦元素一多起来,或退化成一条链,每次GetFather都将会使用O(n)的复杂度,这显然不是我们想要的.对此,我们必须要进行路径压缩,即我们找到最久远的祖先时"顺便"把它的子孙直接连接到它上面.这就是路径压缩了.使用路径压缩的代码如下,时间复杂度基 本可以认为是常数的. 路径压缩可以采用迭代和递归方式递归方式实现简单但是有些题目会爆栈的. //递归形式的路径压缩 int getf(int v) { if(v==f[v]) return v; retu

Codeforces 870E Points, Lines and Ready-made Titles:并查集【两个属性二选一】

题目链接:http://codeforces.com/problemset/problem/870/E 题意: 给出平面坐标系上的n个点. 对于每个点,你可以画一条经过这个点的横线或竖线或什么都不画. 两条重合的直线算作一条直线. 问你能画出多少种不同的图案. 题解: 将所有横坐标或纵坐标相同的两点之间连边. 对于一个连通块,设这个连通块中不同的横坐标个数为sx,不同的纵坐标个数为sy. 有可能画出的线的个数即为sx + sy. 可以发现,如果一个联通块中有环(即siz[fa] >= sx +

并查集(两个版本)

1 import java.util.*; 2 3 public class DisjointUnionSets1{ 4 int[] rank, parent,size; 5 int n; 6 7 public DisjointUnionSets1(int n){ 8 rank = new int[n]; 9 parent = new int[n]; 10 size = new int[n]; 11 this.n = n; 12 makeSet(); 13 } 14 15 void makeSe