3562: [SHOI2014]神奇化合物

题目链接

题目大意:维护一张弦图,支持加边、删边和询问图中有多少个联通块

题解:这是smg……Orz

我的收获:利用询问较少的特性……

#include <map>  
#include <vector>  
#include <cstdio>  
#include <cstring>  
#include <iostream>  
#include <algorithm>  
#define M 5050  
using namespace std;  
int n,m,q;  
map<pair<int,int>,bool> edges;  
struct Query{  
    int type,x,y;  
    //1-A 2-D 3-Q  
    friend istream& operator >> (istream &_,Query &q)  
    {  
        char p[10];  
        scanf("%s",p);  
        if(p[0]=='A')  
            q.type=1,scanf("%d%d",&q.x,&q.y);  
        else if(p[0]=='D')  
        {  
            q.type=2;  
            scanf("%d%d",&q.x,&q.y);  
            if( edges.find( make_pair(q.x,q.y) )!=edges.end() )  
                edges[make_pair(q.x,q.y)]=true;  
            else if( edges.find( make_pair(q.y,q.x) )!=edges.end() )  
                edges[make_pair(q.y,q.x)]=true;  
        }  
        else  
            q.type=3;  
        return _;  
    }  
}queries[10100];  
vector<int> g[M];  
namespace Union_Find_Set{  
    int fa[M],size[M];  
    int Find(int x)  
    {  
        if(!fa[x])  
            fa[x]=x,size[x]=1;  
        if(fa[x]==x)  
            return fa[x]=x;  
        return fa[x]=Find(fa[x]);  
    }  
    void Union(int x,int y)  
    {  
        x=Find(x);y=Find(y);  
        if(x==y) return ;  
        if(size[x]>size[y])  
            swap(x,y);  
        fa[x]=y;size[y]+=size[x];  
    }  
}  
using namespace Union_Find_Set;  
int v[M],T;  
void DFS(int x)  
{  
    vector<int>::iterator it;  
    v[x]=T;  
    for(it=g[x].begin();it!=g[x].end();it++)  
        if(v[*it]!=T)  
            DFS(*it);  
}  
int Get_Ans()  
{  
    int i,re=0;++T;  
    for(i=1;i<=n;i++)  
        if(Find(i)==i&&v[i]!=T)  
            ++re,DFS(i);  
    return re;  
}  
int main()  
{  
    int i,x,y;  
    cin>>n>>m;  
    for(i=1;i<=m;i++)  
    {  
        scanf("%d%d",&x,&y);  
        edges[make_pair(x,y)]=false;  
    }  
    cin>>q;  
    for(i=1;i<=q;i++)  
        cin>>queries[i];  
    map<pair<int,int>,bool>::iterator it;  
    for(it=edges.begin();it!=edges.end();it++)  
    {  
        x=Find(it->first.first);  
        y=Find(it->first.second);  
        if(!it->second)  
            Union(x,y);  
    }  
    for(it=edges.begin();it!=edges.end();it++)  
    {  
        x=Find(it->first.first);  
        y=Find(it->first.second);  
        if(it->second)  
            g[x].push_back(y),g[y].push_back(x);  
    }  
    for(i=1;i<=q;i++)  
    {  
        if(queries[i].type==1)  
        {  
            x=Find(queries[i].x);y=Find(queries[i].y);  
            g[x].push_back(y);g[y].push_back(x);  
        }  
        else if(queries[i].type==2)  
        {  
            x=Find(queries[i].x);y=Find(queries[i].y);  
            vector<int>::iterator it;  
            for(it=g[x].begin();it!=g[x].end();it++)  
                if(*it==y)  
                {  
                    g[x].erase(it);  
                    break;  
                }  
            for(it=g[y].begin();it!=g[y].end();it++)  
                if(*it==x)  
                {  
                    g[y].erase(it);  
                    break;  
                }  
        }  
        else  
            printf("%d\n",Get_Ans());  
    }  
    return 0;  
}  
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值