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

 

posted @ 2010-08-25 23:09  菜到不得鸟  阅读(268)  评论(0)    收藏  举报