题目
数据
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;
}
}
}
}
思路②
直接用普通并查集