題目連結: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;
}