P5214 [SHOI2014] 神奇化合物

Captainfly19發表於2024-05-09

題目連結:https://www.luogu.com.cn/problem/P5214

題意:給定一張無向圖,分別進行以下操作:

Q:詢問圖中有多少連通塊;

A u v :代表在 u v之間連結一條邊;

D u v:代表刪除連結u v的邊。

做法:考慮到題目資料範圍較小,直接用鄰接表存邊即可。
可以發現有些點是不會進行改變的,可以講線上詢問轉成離線,透過並查集將不會改變的點進行縮點,縮點處理之後建立一張新圖。由於資料範圍小,對於每次查詢操作在圖上進行暴力搜尋連通塊即可。增邊刪邊操作只需對鄰接表加減操作即可。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> PII;
#define mp make_pair
#define ull unsigned long long
inline int gcd(int a, int b){return b == 0 ? a : gcd(b, a % b);}
inline int lcm(int a, int b){return a / gcd(a, b) * b;}
const ll mod = 998244353;
ll powmod(ll a,ll b) {ll res=1;a%=mod; assert(b>=0); for(;b;b>>=1){if(b&1)res=res*a%mod;a=a*a%mod;}return res;}
inline int read()
{
int X=0; bool flag=1; char ch=getchar();
while(ch<'0'||ch>'9') {if(ch=='-') flag=0; ch=getchar();}
while(ch>='0'&&ch<='9') {X=(X<<1)+(X<<3)+ch-'0'; ch=getchar();}
if(flag) return X;
return ~(X-1);
}
#define maxn 5010
#define N 10010
#define int long long
int vec[maxn][maxn];
char c[N];
int p[maxn];
int l[N],r[N];
int x[200010],y[200010];
vector<int> g[maxn];
int find(int x){
    if(p[x]!=x)
    {
        p[x]=find(p[x]);
    }
    return p[x];
}
void uni(int a,int b)
{
    int x=find(a);
    int y=find(b);
    if(x!=y)
    {
        p[x]=y;
    }
}
int vis[maxn];
inline void dfs(int now)
{
    vis[now]=1;
    for(auto to:g[now])
    {
        if(!vis[to]&&vec[now][to])
        {
            dfs(to);
        }
    }
}
signed main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    int n,m;
    cin>>n>>m;
    for(int i=1;i<=n;i++)
    {
        p[i]=i;
    }
    for(int i=1;i<=m;i++)
    {
        cin>>x[i]>>y[i];
        vec[x[i]][y[i]]=vec[y[i]][x[i]]=1;
    }
    int q;
    cin>>q;
    for(int i=1;i<=q;i++)
    {
        cin>>c[i];
        if(c[i]!='Q')
        {
            cin>>l[i]>>r[i];
        }
        if (c[i]=='D')
        {
            vec[l[i]][r[i]]=vec[r[i]][l[i]]=0;
        }
    }
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=n;j++)
        {
            if(vec[i][j])
            {
                uni(i,j);
            }
        }
    }
    memset(vec,0,sizeof(vec));
    for(int i=1;i<=m;i++)
    {
        if(!vec[find(x[i])][find(y[i])])
        {
            g[find(x[i])].push_back(find(y[i]));
            g[find(y[i])].push_back(find(x[i]));
        }
        vec[find(x[i])][find(y[i])]++;
        vec[find(y[i])][find(x[i])]++;
    }
    for(int i=1;i<=q;i++)
    {
        if(c[i]=='D')
        {
            vec[find(l[i])][find(r[i])]=vec[find(r[i])][find(l[i])]=max(1ll*0,
            vec[find(l[i])][find(r[i])]-1);
        }
        else if(c[i]=='A')
        {
            if(!vec[find(l[i])][find(r[i])])
            {
                g[find(l[i])].push_back(find(r[i]));
                g[find(r[i])].push_back(find(l[i]));
            }
            vec[find(l[i])][find(r[i])]++;
            vec[find(r[i])][find(l[i])]++;
        }
        else
        {
            memset(vis,0,sizeof(vis));
            int ans=0;
            for(int j=1;j<=n;j++)
            {
                if(!vis[find(j)])
                {
                    dfs(find(j));
                    ans++;
                }
            }
            cout<<ans<<endl;
        }
    }
    return 0;

}

相關文章