POJ1703(并查集,经典问题,对立问题)

Find them, Catch them
Time Limit: 1000MS

Memory Limit: 10000K
Total Submissions: 52870

Accepted: 16192
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
    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.
    题目中 有两个对立项,分析关系就是敌人的敌人就是朋友,曾经做过一个虫子雌雄的问题与该题相似,我记录下敌人,那么我所有的敌人就是一伙的了,判断时就可以判断若该人和我的敌人是一伙的,那他就是我的敌人,若我和他的敌人是一伙的,那他也是我的敌人,它既不是我的朋友,我不是我的敌人,那他就跟我没关系。

//并查集经典问题
//敌人的敌人是朋友
//我爱的女孩爱的人是男人(这可不一定)
#include<iostream>
#include<algorithm>
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<queue>
#define MAXN 100005
using namespace std;
int father[MAXN];//并查集,表示是否连通
int enemy[MAXN];//敌人
int n,m;

int mfind(int x){
    int r = x;
    while(r!=father[r]){
        r = father[r];
    }
    int i = x,j;
    while(i!=r){
        j = father[i];
        father[i] = r;
        i =j;
    }
    return r;//返回根节点
}
void connect(int x,int y){
    int nx = mfind(x);
    int ny = mfind(y);
    if(nx!=ny){
        father[nx] = ny;
    }
}
int main()
{
    int T;
    scanf("%d",&T);
    while(T--){
        scanf("%d%d",&n,&m);

        //初始化
        memset(enemy,0,sizeof(enemy));//开始没有敌人
        for(int i=0;i<=n;i++){
            father[i] = i;
        }

        char operation;
        getchar();
        for(int i=0;i<m;i++){
            scanf("%c",&operation);
            if(operation=='A'){
                int peo1,peo2;
                scanf("%d%d",&peo1,&peo2);
                if(mfind(peo1)==mfind(peo2)){
                    printf("In the same gang.\n");
                }
                else{
                    if(mfind(peo1)==enemy[peo2]||mfind(enemy[peo1])==mfind(peo2)){
                        printf("In different gangs.\n");
                    }
                    else{
                        printf("Not sure yet.\n");
                    }
                }
            }
            else{
                int tmp1,tmp2;
                scanf("%d%d",&tmp1,&tmp2);
                if(enemy[tmp1]){//如果我有敌人,他就是跟我敌人一伙的
                    connect(enemy[tmp1],tmp2);
                }
                else{//我没有敌人,他就是是我唯一的敌人,我会永远记住他
                    enemy[tmp1] = tmp2;
                }
                //同时,他是我的敌人,我就是他的敌人。
                if(enemy[tmp2]){
                    connect(tmp1,enemy[tmp2]);
                }
                else{
                    enemy[tmp2] = tmp1;
                }
            }
            getchar();
        }
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_40488730/article/details/81564428