思路:也是并查集,逆向思维,题目要求先把边所有边连起来,再去删; 那可以这样想,先(除去需要删的边)把边连起来(这里可以排序实现),在倒着执行操作,把删边当做连边操作即可
一开始把前面的边保存起来,然后去掉后面为D的边,倒着执行D和P的操作(即遇到d,就可并a,b),答案倒着输出即可

#include<stdio.h>
#include<iostream>
#include<algorithm>
using namespace std;
#define N 100009
struct data
{
int x;
int y;
}bian[200009];
struct data1
{
char ss;
int x,y;
}cun[N];
int f[N];
char end[N];
bool cmp(data a,data b)
{
if(a.x==b.x)return a.y<b.y;
return a.x<b.x;
}
int find(int pos)
{
if(f[pos]==-1)return pos;
return f[pos]=find(f[pos]);
}
int un(int a,int b)
{
int fa=find(a);
int fb=find(b);
if(fa==fb)return 0;
f[fa]=fb;return 1;
}
int main()
{
int n,m,i,a,b,temp,cao;
while(scanf("%d%d",&n,&m)!=EOF)
{
for(i=1;i<=n;i++)
{
f[i]=-1;
}
for(i=1;i<=m;i++)
{
scanf("%d%d",&a,&b);
if(a>b)
{
temp=a;
a=b;
b=temp;
}
bian[i].x=a;
bian[i].y=b;
}
scanf("%d",&cao);
char ss;
for(i=1;i<=cao;i++)
{
getchar();//小心
scanf("%c",&ss);
scanf("%d%d",&a,&b);
if(a>b)
{
temp=a;
a=b;
b=temp;
}
cun[i].ss=ss;
cun[i].x=a;
cun[i].y=b;
bian[i+m].x=a;
bian[i+m].y=b;
}
sort(&bian[1],&bian[1+m+cao],cmp);
for(i=1;i<m+cao;i++)
{
if(bian[i].x==bian[i+1].x&&bian[i].y==bian[i+1].y)
{}
else
un(bian[i].x,bian[i].y);
}
int add=1;
for(i=cao;i>=1;i--)
{
if(cun[i].ss=='Q')
{
a=find(cun[i].x);
b=find(cun[i].y);
if(a==b)
end[add]='C';
else
end[add]='D';
add++;
}
else
{
a=find(cun[i].x);
b=find(cun[i].y);
un(a,b);
}
}
for(i=add-1;i>=1;i--)
{
printf("%c\n",end[i]);
}
}
return 0;
}