数据结构算法——1083. 小强的烦恼

题目

在这里插入图片描述
数据
1
6 9
Q 1 2
A 1 2
Q 1 2
A 3 4
Q 1 3
A 5 6
A 4 5
Q 3 6
Q 4 6

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

思路

详见注释

代码

#include<iostream>
#include<map>
using namespace std;
struct dot
{
    int father;//同一个集合
    int tag;//阵营
};
map<int,dot>ma;
pair<int,int> find(int x)
{
    if(ma[x].father == x)   return{x,0};
    //如果自己是自己的祖先,自然返回0,因为自己是自己的朋友
    pair<int,int>p = find(ma[x].father);//递归找自己的祖先
    ma[x].father = p.first;
    ma[x].tag = (ma[x].tag + p.second) % 2;
    return {ma[x].father, ma[x].tag};
}
//find的作用是重新计算x的阵营,并且让x和祖先中间所有节点直接作为祖先的直接子结点
//由于阵营有滞后性,所以会根据x本身到祖先之间的结点tag进行累加并%2得到最后的阵营

int get_father(int x)
{
    find(x);
    return ma[x].father;
}

void U(int x, int y)
{
    //将x,y设定为敌人
    find(x);find(y);//确定x和y的祖先和阵营
    int x_father = ma[x].father;
    ma[x_father].tag = (1 + ma[y].tag + ma[x].tag) % 2;
    ma[x_father].father = ma[y].father;//将x父亲和y放在确定关系集合中

}
    

int query(int x, int y)
{
    if(get_father(x) == get_father(y))
    {
        if(ma[x].tag == ma[y].tag)  return 0;//表示同一个阵营
        else return 1;//不同阵营
    }
    return -1;//没确认关系
        
}

int main()
{
    int t;
    cin >> t ;
    for(int i = 0; i < t; i++)
    {
        int n,m;
        cin >> n >> m;
        for(int i = 1; i < n; i++)
        {
            //初始化
            ma[i].father = i;
            ma[i].tag = 0;
        }
        for(int i = 0; i < m; i++)
        {//询问问题
            char que;
            int x,y;
            cin >> que >> x >> y;
            switch(que)
            {
            case 'A':
                if(query(x,y) == -1)//询问是否确定关系
                    U(x,y);//-1没确定 将他们进行一个合并,合并到确定关系的集合中
            break;
            case 'Q':
                int t = query(x,y);
                if(t == 1)
                    cout << "In different gangs." << endl;
                else if(t == 0)
                    cout << "In the same gang." << endl;
                else
                    cout <<"Not sure yet." << endl;

            break;
            }
        }
    }
}

思路②

直接用普通并查集

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值