题目描述
NE给你了一个挑战,来测试你的实力:
他查阅了历史上势力之间的关系变动,并想推演整个英仙座的势力情况,你能帮他完成这个任务吗?
NE会不断进行如下五种操作,格式如下:
1 A B 势力A和势力B进行结盟,注意:当A和B成为盟友时,A、B以及A、B的所有盟友之间都会成为盟军
2 A B 势力A和当前所有的盟军势力取消盟军关系,并和势力B成为盟军
3 A 查询势力A的盟军的数量
4 A B 查询势力A和势力B是否为盟军
5 A B 势力A和势力B出现了隐藏的历仇恨,势力间的仇恨并不影响势力的行为,但是会一直存在。
在进行完所有的推演之后,最后NE想选择一个联盟加入,同时这个联盟的内部势力之间不存在隐藏的仇恨。
NE并不在乎他到底加入了具体哪个联盟,他只想知道他加入的联盟最大能有多大。
输入描述
输入第一行包含两个数字n,m分别代表势力数和操作数1≤n,m≤〖10〗^6
接下来m行,每行代表一次操作,5种操作的格式如上所述。
输出描述
对于操作3、4,每次输出一行,即为所求的答案。
特别地,对于操作4,若A,B为盟军,输出"Yes \"",否则输出"No"。
结束所有操作之后,输出一行,包含一个整数,即为最大的联盟大小,如果不存在这样的联盟,则输出-1。
样例输入 1
5 5 1 2 3 2 3 4 3 2 4 4 2 5 3 4
样例输出 1
0 No 1
主要是操作2 :理解下面例子就可以了
例子:食品店要给顾客甲派送食物food装在箱子box里,box有个挂钩(挂钩就相当于连接父节点的边)。food[]存储箱子编号,box[]存父节点。
food有很多,把要送的归在一类后。顾客甲打电话退订了某些。
如下图,food[2]=2.编为2的food它的箱子box编号是2
box[3]=3;编号为3的箱子box它的挂钩挂在自己上(它的父节点是它自己)。
建立如下并查集树。box[3]=2;
然后顾客甲打电话要退订编号为4,6的food。
接下来我们只需要把编号为4的food拿走,用编号为n++(7)的箱子装起来。
food[4]=7;
box[7]=[7];
编号为4的箱子依然留在那里,这样就不影响编号4的box后面挂的箱子的根节点就不会丧失。
拿走6同理。
food[6]=8;
box[8]=8;
接下来又有一顾客乙要走了4,6.
box[food[6]]=food[4];\\把编号为6的food它所在的箱子8的挂钩挂到编号为4的food它所在的箱子7上。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<map>
#include<vector>
#include<set>
#include<queue>
#include<algorithm>
#include<stack>
#include<cstdlib>
#include<deque>
#include<bitset>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int>P;
const int len=2e6+5;
const double pi=acos(-1.0);
const ll mod=1e8+7;
int food[len],box[len],num[len];
int tot;
vector<P>ve;
int find(int x)
{
if(x==box[x])return x;
return box[x]=find(box[x]);
}
void mer(int x,int y)
{
x=find(food[x]);
y=find(food[y]);
if(x==y)return ;
num[x]+=num[y];
box[y]=x;
num[y]=0;
}
void update(int x,int y)
{
num[find(food[x])]--;
food[x]=++tot;
box[tot]=tot;
num[tot]=1;
mer(x,y);
}
int main()
{
int n,m;
cin>>n>>m;
tot=n;
for(int i=1;i<=n;++i)
{
box[i]=i;
food[i]=i;
num[i]=1;
}
for(int i=1;i<=m;++i)
{
int op,x,y;
scanf("%d%d",&op,&x);
if(op!=3)scanf("%d",&y);
if(op==1)mer(x,y);
else if(op==2)update(x,y);
else if(op==3)printf("%d\n",num[find(food[x])]-1);
else if(op==4)find(food[x])==find(food[y])?puts("Yes"):puts("No");
else ve.push_back({x,y});
}
int ans=-1;
for(int i=0;i<ve.size();++i)
if(find(food[ve[i].first])==find(food[ve[i].second]))num[find(food[ve[i].second])]=-1;
for(int i=1;i<=n;++i)
ans=max(ans,num[find(food[i])]);
cout<<ans<<endl;
}