nuaa 1087 连通 OR 不连通
http://acm.nuaa.edu.cn/acmhome/problemdetail.do?&method=showdetail&id=1087
思路:反过来做的题目,先将所有边和操作存起来,遇到'D'则标记;将未标记的边用并查集并起来;倒着一系列的操作,遇到'D'则合并,遇到'Q'则普通地查询并查集,将答案存起来。最后倒着答案输入,理解理解。。。
#include <stdio.h>
#include <string.h>
#include <map>
using namespace std;
#define MAXNM 100002
#define MAXQ 100002
typedef __int64 ll;
struct ENode
{
int u,v;
} edge[MAXNM];
struct OperNode
{
char op;
int u,v;
} oper[MAXQ];
map<ll,bool> isdel;
int father[MAXNM];
char ans[MAXQ];
inline ll gethash(int x,int y)
{
return x*MAXNM+y;
}
int find(int x)
{
int i,t;
for(i=x; father[i]>0; i=father[i]) ;
while(x!=i)
{
t=father[x];
father[x]=t;
x=t;
}
return i;
}
void merge(int x,int y)
{
int fx=find(x),fy=find(y);
if(fx==fy) return;
if(father[fx]>father[fy])
{
father[fy]+=father[fx];
father[fx]=fy;
}
else
{
father[fx]+=father[fy];
father[fy]=fx;
}
}
int main()
{
int n,m,i,j,k,q;
ll hv;
char ch[2];
while(scanf("%d %d",&n,&m)!=EOF)
{
memset(father,-1,sizeof(*father)*(n+1));
for(k=0; k<m; k++)
{
scanf("%d %d",&i,&j);
if(i>j) i^=j^=i^=j;
edge[k].u=i;
edge[k].v=j;
hv=gethash(i,j);
isdel[hv]=false;
}
scanf("%d",&q);
for(k=0; k<q; k++)
{
scanf("%s %d %d",ch,&i,&j);
if(i>j) i^=j^=i^=j;
oper[k].u=i;
oper[k].v=j;
if(ch[0]=='Q') oper[k].op='Q';
else
{
oper[k].op='D';
hv=gethash(i,j);
isdel[hv]=true;
}
}
for(k=0; k<m; k++)
{
hv=gethash(edge[k].u,edge[k].v);
if(isdel[hv]==false) merge(edge[k].u,edge[k].v);
}
i=q-1;
ans[q]=0;
for(k=q-1; k>=0; k--)
{
if(oper[k].op=='Q')
{
j++;
if( find( oper[k].u ) == find( oper[k].v ) )
ans[i--]='C';
else ans[i--]='D';
}
else
{
merge(oper[k].u,oper[k].v);
}
}
for(k=i+1; ans[k]; k++)
{
printf("%c\n",ans[k]);
}
}
return 0;
}
浙公网安备 33010602011771号