Find them, Catch them(带权值的并查集)

来源:互联网 发布:淘宝怎么再次申请退款 编辑:程序博客网 时间:2024/06/08 08:40
Find them, Catch them
Time Limit: 1000MS Memory Limit: 10000KTotal Submissions: 44642 Accepted: 13751

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 belongs to. The present question is, given two criminals; do they belong to a same clan? You must give your judgment based on incomplete information. (Since the gangsters are always acting secretly.) 

Assume N (N <= 10^5) criminals are currently in Tadu City, numbered from 1 to N. And of course, at least one of them belongs to Gang Dragon, and the same for Gang Snake. You will be given M (M <= 10^5) messages in sequence, which are in the following two kinds: 

1. D [a] [b] 
where [a] and [b] are the numbers of two criminals, and they belong to different gangs. 

2. A [a] [b] 
where [a] and [b] are the numbers of two criminals. This requires you to decide whether a and b belong to a same gang. 

Input

The first line of the input contains a single integer T (1 <= T <= 20), the number of test cases. Then T cases follow. Each test case begins with a line with two integers N and M, followed by M lines each containing one message as described above.

Output

For each message "A [a] [b]" in each case, your program should give the judgment based on the information got before. The answers might be one of "In the same gang.", "In different gangs." and "Not sure yet."

Sample Input

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

Sample Output

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

Source

POJ Monthly--2004.07.18

题意:
就是有两个帮派,岗龙和岗蛇帮,现在就是判断是不是属于同一个帮派
T 代表几组测试数据;
N代表有多少个帮派; 
M代表接下来几行询问
-----
A 1 2 //询问1和2是否属于同一个帮派-----输出Not sure yet.D 1 2 //表示1和2不属于同一个帮派A 1 2 //询问1和2是否属于同一个帮派-----输出In different gangs.  D 2 4 //表示2和4不属于同一个帮派A 1 4 //询问1和4是否属于同一个帮派-----输出In the same gangs.
上面的D是累加的,也就是每次的出现都是保留下来的,没有覆盖更新。

/*并查集的集合是以能否确定关系来分的,而不是以属于同一个帮派或不同帮派来分的
这类题只需建立一个并查集,然后维护每个结点和他的根结点之间的关系属性即可
如果2个点不在同一个并查集中,那么这2个点无法确定关系
在同一个并查集中的每个点,都能确定集合中的相互关系
定义一个数组c表示两个派别,0和1,初始化为0。*/

第一步:
首先确定用0、1分别标记某一个节点和树根的同、异帮派关系
第二步:
可以先认为每个节点都是树根且都是与自身同帮派,据此初始化标记变量
第三步:
对每组输入数据进行处理,若两个节点的根结点不同,若输入A操作,则无法确定二者的帮派是否相同;
若为D操作,则合并两个节点所在的树且更新节点的关系;
若两个节点的根结点相同,则根据这两个节点的与根结点的关系来判断这两个节点的关系。

#include<iostream>#include<cstdio>#include<algorithm>#include<cstdlib>#include<cstring>using namespace std;int f[110000],c[110000];int find(int x){    if(f[x]==x)        return x;    int t=f[x];//先将当前结点x的父亲保存下来    f[x]=find(f[x]);//递归找父亲顺便路径压缩,这时候f[x]存放的就是这颗树的根了    c[x]=(c[x]+c[t])%2;//通过这条递推式在路径压缩的时候更新状态    return f[x];//返回根}int make(char ch,int a,int b){    int f1=find(a);    int f2=find(b);    if(f1!=f2)    {        if(ch=='A')            return 0;        f[f1]=f2;        if((c[a]+c[b])%2==0)//通过a和b的c关系来更新a根结点的c            c[f1]=1;    }    else    {        if(ch=='A')        {            if(c[a]!=c[b])  return 1;//当前的两个结点如果不在同一颗树上,就无法判定他们是否属相同帮派            if(c[a]==c[b])  return 2;        }    }    if(ch=='D')        return 3;}int main(){    int ca,i,n,m;    scanf("%d",&ca);    while(ca--)    {        scanf("%d%d",&n,&m);        getchar();        for(i=1;i<=n;i++)//定义一个数组表示两个派别,0和1,初始化为0        {            f[i]=i;            c[i]=0;        }        char ch;        int a,b;        for(i=1;i<=m;i++)        {            scanf("%c%d%d",&ch,&a,&b);            getchar();            int t=make(ch,a,b);            if(t==0)                printf("Not sure yet.\n");            else if(t==1)                printf("In different gangs.\n");            else  if(t==2)                printf("In the same gang.\n");            else                continue;        }    }    return 0;}


0 0
原创粉丝点击