x y L其实表示x和y不同,x y T表示x和y相同。
rank[x]表示第x个元素和其根节点的关系,rank[x]=1表示和根节点不同,rank[x]=0表示和根节点相同。
特别注意当B集合合并到A集合的时候,B集合的根节点的rank值需要更新,且其所有子节点也可能需要更新,在路径压缩的时候进行特殊处理确保子节点能够得到正确的rank值。
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cstdio>
#include <vector>
using namespace std;
int parent[10005];
int rank[10005];
char s[2];
int getpar(int a)
{
if (parent[a]!=a)
{
int tempar=getpar(parent[a]);
if (rank[parent[a]])
rank[a]=!rank[a];
parent[a]=tempar;
}
return parent[a];
}
void unio(int x,int y)
{
int xp=getpar(x);
int yp=getpar(y);
parent[yp]=xp;
if ( (s[0]=='T' && rank[x]!=rank[y]) || (s[0]=='L' && rank[x]==rank[y]) )
rank[yp]=1;
}
int main()
{
int m,n,x,y,i,j;
bool end=false;
scanf("%d%d",&m,&n);
int record=n;
for (i=1;i<=m;i++)
parent[i]=i;
for (i=0;i<n;i++)
{
scanf("%d%d%s",&x,&y,s);
if (!end)
{
int xp=getpar(x);
int yp=getpar(y);
if (xp==yp)
{
if ((s[0]=='L' && rank[x]==rank[y]) || (s[0]=='T' && rank[x]!=rank[y]))
{
end=true;
record=i;
}
}
else
unio(x,y);
}
}
printf("%d\n",record);
}