维护两个并查集 f1与f2
题目中所给两点间的关系都是对立的 而一共只有两个阵营 因此可以得出 a敌对b且b敌对c 则a与c为同伙
对于两点间关系的询问 首先要看两点之间的敌友关系是否已经确定 如果以敌对关系为边建立子图 则图中相邻两点为敌 间隔一点为友 以此类推 因此只要两点连通即可确定关系 可通过并查集f1实现
其次要看是敌还是友 可通过标记数组实现 比如新增a敌对b 如果之前还有a敌对c那就把b与c放入友好并查集f2 敌友关系即可明了
using namespace std;
struct node
{
    int id;
    int sta;
};
node book[100010];
int f1[100010],f2[100010];
int n,m;
void unite(int u,int v,int* f);
int getf(int p,int* f);
int main()
{
    int t,i,j,u,v,fu,fv;
    char ch[2];
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d%d",&n,&m);
        memset(book,0,sizeof(book));
        for(i=1;i<=n;i++)
        {
            f1[i]=i;
            f2[i]=i;
        }
        for(i=1;i<=m;i++)
        {
            scanf("%s%d%d",ch,&u,&v);
            if(ch[0]=='D')
            {
                unite(u,v,f1);
                if(book[u].sta==1)
                {
                    unite(book[u].id,v,f2);
                }
                else
                {
                    book[u].id=v;
                    book[u].sta=1;
                }
                if(book[v].sta==1)
                {
                    unite(book[v].id,u,f2);
                }
                else
                {
                    book[v].id=u;
                    book[v].sta=1;
                }
            }
            else
            {
                fu=getf(u,f1);
                fv=getf(v,f1);
                if(fu!=fv)
                {
                    printf("Not sure yet.\n");
                }
                else
                {
                    fu=getf(u,f2);
                    fv=getf(v,f2);
                    if(fu!=fv)
                    {
                        printf("In different gangs.\n");
                    }
                    else
                    {
                        printf("In the same gang.\n");
                    }
                }
            }
        }
    }
    return 0;
}
void unite(int u,int v,int* f)
{
    int fu,fv;
    fu=getf(u,f);
    fv=getf(v,f);
    if(fu!=fv)
    {
        f[fv]=fu;
    }
    return;
}
int getf(int p,int* f)
{
    if(f[p]==p) return p;
    else
    {
        f[p]=getf(f[p],f);
        return f[p];
    }
}
用种类并查集的话就是个裸题了
using namespace std;
const int maxn=1e5+10;
int f[maxn],dis[maxn];
int n,q;
int getf(int p)
{
  int res;
  if(f[p]==p) return p;
  res=getf(f[p]);
  dis[p]=(dis[f[p]]+dis[p])%2;
  f[p]=res;
  return res;
}
void unite(int u,int v)
{
  int fu,fv;
  fu=getf(u),fv=getf(v);
  if(fu!=fv){
    f[fv]=fu;
    dis[fv]=(dis[u]+dis[v]+1)%2;
  }
}
int solve(int u,int v)
{
  int fu,fv;
  fu=getf(u),fv=getf(v);
  if(fu!=fv){
    return 0;
  }
  else{
    if(dis[u]==dis[v]) return 1;
    else return 2;
  }
}
int main()
{
  int t,u,v,res,i;
  char op[10];
  scanf("%d",&t);
  while(t--){
    scanf("%d%d",&n,&q);
    for(i=1;i<=n;i++){
      f[i]=i,dis[i]=0;
    }
    while(q--){
      scanf("%s%d%d",op,&u,&v);
      if(op[0]=='A'){
        res=solve(u,v);
        if(res==0) printf("Not sure yet.\n");
        else if(res==1) printf("In the same gang.\n");
        else printf("In different gangs.\n");
      }
      else{
        unite(u,v);
      }
    }
  }
  return 0;
}
                










