【POJ - 1703】Find them, Catch them(种类并查集)

Find them, Catch them

直接翻译了

Descriptions

警方决定捣毁两大犯罪团伙:龙帮和蛇帮,显然一个帮派至少有一人。该城有N个罪犯,编号从1至N(N<=100000。将有M(M<=100000)次操作。
D a b 表示a、b是不同帮派
A a b 询问a、b关系


Input

多组数据。第一行是数据总数 T (1 <= T <= 20)每组数据第一行是N、M,接下来M行是操作


Output

对于每一个A操作,回答"In the same gang."或"In different gangs." 或"Not sure yet."


Sample Input

1
5 5
A 1 2
D 1 2
A 1 2
D 2 4
A 1 4

Sample Output

Not sure yet.
In different gangs.
In the same gang.

题目链接

https://vjudge.net/problem/POJ-1703

定义并查集为:

并查集里的元素i-x表示i属于帮派x

同一个并查集的元素同时成立

可见所有元素个数为2 * N,如果i表示属于帮派A,那么i + N表示属于帮派B,每次输入两个家伙不在同一帮派的时候,就合并他们分属两个帮派的元素。

注意这题如果用cin的话会TLE

AC代码

#include <iostream>
#include <cstdio>
#include <fstream>
#include <algorithm>
#include <cmath>
#include <deque>
#include <vector>
#include <queue>
#include <string>
#include <cstring>
#include <map>
#include <stack>
#include <set>
#include <sstream>
#define IOS ios_base::sync_with_stdio(0); cin.tie(0);
#define Mod 1000000007
#define eps 1e-6
#define ll long long
#define INF 0x3f3f3f3f
#define MEM(x,y) memset(x,y,sizeof(x))
#define Maxn 100000 * 2 + 10
using namespace std;
int T,N,M;
int par[Maxn];//par[i] i的根
void init(int n)
{
    for(int i=0; i<=n; i++)
        par[i]=i;
}
int findr(int x)//查询根
{
    if(par[x]==x)
        return x;
    return par[x]=findr(par[x]);
}
void unite(int x,int y)//合并
{
    x=findr(x);
    y=findr(y);
    if(x==y)//根相同不用管
        return;
    par[x]=y;//若根不同,y并入x,则y的根为x,同理x也能并入y  这里随意
}
bool same(int x,int y)//x和y是否在一个集合
{
    return findr(x)==findr(y);
}
int main()
{
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d%d",&N,&M);
        init(N*2);
        char op[2];
        int a,b;
        for(int i=0; i<M; i++)
        {
            scanf("%s%d%d", op, &a, &b);
            if(op[0]==‘A‘)
            {
                if(same(a,b))
                    printf("In the same gang.\n");
                else if(same(a,b+N))
                    printf("In different gangs.\n");
                else
                    printf("Not sure yet.\n");
            }
            else
            {
                unite(a+N,b);
                unite(a,b+N);
            }
        }
    }
    return 0;
}

原文地址:https://www.cnblogs.com/sky-stars/p/11332745.html

时间: 2024-10-11 12:17:11

【POJ - 1703】Find them, Catch them(种类并查集)的相关文章

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

题意:N个人,M条关系,A x y表示询问x和y是不是属于同一组,D x y表示x和y是不同组.输出每个询问后的结果. 分析: 1.所有的关系形成一个连通图,如果x和y可达,那两者关系是确定的,否则不能确定. 2.r[tmpy] = r[x] + r[y] + 1;可以更新连通块里祖先的标号. eg: 5 4 D 1 2 D 2 3 D 4 5-----到此为止形成两个连通块,标号如图所示(红笔) D 3 5 第四步,将3和5连边,因为以0为祖先,所以4的标号应当改变,可以发现改变后的r[4]

poj 1703 Find them, Catch them 【并查集拓展】

Find them, Catch them Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 32514   Accepted: 10036 Description The police office in Tadu City decides to say ends to the chaos, as launch actions to root up the TWO gangs in the city, Gang Drago

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

题目传送:Find them, Catch them 思路:用一个关系数组记录当前结点与其父亲的关系,0表示同类,1表示不同类 AC代码: #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #include <cmath> #include <queue> #include <stack> #include <v

HDU 1829 &amp;&amp; POJ 2492 A Bug&#39;s Life(种类并查集)

题目地址:HDU 1829     POJ 2492 这个题可以用两种方法做,第一眼看完题是觉得用dfs染色判断二分图.然后又写的刚学的种类并查集.原来并查集可以这样用,真是神奇.. dfs染色代码: #include <iostream> #include <cstdio> #include <string> #include <cstring> #include <stdlib.h> #include <math.h> #incl

[poj1703]Find them, Catch them(种类并查集)

题意:食物链的弱化版本 解题关键:种类并查集,注意向量的合成. $rank$为1代表与父亲对立,$rank$为0代表与父亲同类. #include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<cstdlib> #include<cmath> using namespace std; typedef long long ll; #de

POJ 2236 Wireless Network ||POJ 1703 Find them, Catch them 并查集

POJ 2236 Wireless Network http://poj.org/problem?id=2236 题目大意: 给你N台损坏的电脑坐标,这些电脑只能与不超过距离d的电脑通信,但如果x和y均能C通信,则x和y可以通信.现在给出若干个操作, O p 代表修复编号为p的电脑 S p q代表询问p和q是不是能通信. 思路: 并查集即可.. 如果修复了一台电脑,则把与它相连距离不超过d的且修复了的放在一个集合里面. #include<cstdio> #include<cstring&

Poj(1703),种类并查集

题目链接:http://poj.org/problem?id=1703 已经不是第一次接触种类并查集了,直到今天才搞懂. 感谢红黑联盟,感谢杰哥!!! 每个节点只要关系确定,不管是不是同一个集合里面,都把他们放到一个集合里面,用一个rank[]数组记录他们与根节点的关系,比较神奇的地方有两处: 1.find函数里面,因为find是递归写的,不断往上找,不断更新rank[x](与根节点的关系),这个%k,也是很牛逼的,2种类型,标号只有01: 2.Union函数里面,更新rank[fy],rank

POJ 1703 Find them, Catch them(数据结构-并查集)

Find them, Catch them Description The police office in Tadu City decides to say ends to the chaos, as launch actions to root up the TWO gangs in the city, Gang Dragon and Gang Snake. However, the police first needs to identify which gang a criminal b

种类并查集,Poj(1703)

题目链接:http://poj.org/problem?id=1703 第一次做种类并查集,有的地方还不是很清楚,想了一上午,有点明白了,这里记录一下. 这里我参考的红黑联盟的题解. 关键:种类并查集与带权并查集实质上的差别并不大, 关键的区别就是种类并查集只是带权并查集再弄个%取余操作而已,然后余数就表示他属于哪个种类. rank数组表示节点和父节点的关系(也可以理解为他的种类). find中,找到x的父节点后,那么更新他与父节点的关系,rank[x] = (rank[x]+rank[fa])

POJ1703--Find them, Catch them(种类并查集)

Time Limit: 1000MSMemory Limit: 10000K Total Submissions: 32909Accepted: 10158 Description The police office in Tadu City decides to say ends to the chaos, as launch actions to root up the TWO gangs in the city, Gang Dragon and Gang Snake. However, t