题目链接: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;
}
标签:P5214,int,ll,ch,vec,SHOI2014,now,find,神奇
From: https://www.cnblogs.com/captainfly/p/18183342