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); }