并查集+删边操作——nuaa1087

思路:也是并查集,逆向思维,题目要求先把边所有边连起来,再去删;  那可以这样想,先(除去需要删的边)把边连起来(这里可以排序实现),在倒着执行操作,把删边当做连边操作即可
一开始把前面的边保存起来,然后去掉后面为D的边,倒着执行D和P的操作(即遇到d,就可并a,b),答案倒着输出即可
View Code
#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;
}
原文地址:https://www.cnblogs.com/huhuuu/p/1970231.html