并查集简单题
code:(容易思考,但也容易超时)
初始化注意题目初始化的范围,从1还是从0
分组“D”时,b,c不是在同一个组里,转换,按照b,c+n在同一组和c,c+n在同一组操作
get:一般不会改变合并函数,解题一般会转化到合并思想上来,而不是写拆分函数
#include <iostream>
#include <iostream>
#include <string>
using namespace std;
const int maxn=100000+5;
int s[2*maxn];
int h[2*maxn];
void init(int n)//初始化,注意题目初始化的范围
{
for(int i=1; i<=2*n; i++)
{
s[i]=i;
h[i]=1;
}
}
int find_s(int x)
{
return x==s[x]?x:find_s(s[x]);
}
void union_s(int x,int y)
{
int i=find_s(x);
int j=find_s(y);
/*if(i!=j)
{
s[i]=s[j];
h[i]+=h[j];
}*/
/*if(i!=j) //单链也可进行优化
{
if(h[i]==h[j])
{
s[j]=i;
h[i]++;
}
else
{
if(h[i]<h[j])
s[i]=j;
else
s[j]=i;
}
}*/
if(i!=j) //代码简化
{
if(h[i]<h[j])
s[i]=j;
else
{
s[j]=i;
if(h[i]==h[j])
{
h[i]++;
}
}
}
}
bool same(int x,int y)
{
return find_s(x)==find_s(y);
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int t;
cin>>t;
while(t--)
{
int n,m;
cin>>n>>m;
string a;
int b,c;
init(n);
while(m--)
{
cin>>a>>b>>c;
if(a=="D")
{
union_s(b,c+n);
union_s(b+n,c);
}
else
{
if(same(b,c))
cout<<"In the same gang."<<endl;
else if(same(c,b+n))
cout<<"In different gangs."<<endl;
else
cout<<"Not sure yet."<<endl;
}
}
}
return 0;
}
之前
写的代码
一直没有使用路径压缩优化
int find_s(int x)
{
int r=x;
while(s[r]!=r) r=s[r];
int i=x,j;
while(i!=r)
{
j=s[i];
s[i]=r;
i=j;
}
return r;
}