题面
题意
给定无向图,每次删去一个点并求连通分量个数。
题解
很难在删除点的同时维护联通分量个数,但是如果把操作倒序,问题就变成了每次往无向图里添加一个点并求连通分量个数。可以用并查集维护。 代码
#include<iostream> #include<cstdio> #include<vector> using namespace std; const int maxn=4e5+5; vector<int> e[maxn]; int fa[maxn]; bool vis[maxn]; int arr[maxn],ans[maxn]; int ff(int u){ return fa[u]==u?u:fa[u]=ff(fa[u]); } int main(){ int i,j,n,m; int u,v; int cnt; scanf("%d%d",&n,&m); while (m--){ scanf("%d%d",&u,&v); e[u].push_back(v); e[v].push_back(u); } scanf("%d",&m); for (i=0;i<n;i++){ fa[i]=i; vis[i]=true; } for (i=0;i<m;i++){ scanf("%d",&arr[i]); vis[arr[i]]=false; } cnt=n-m; for (i=0;i<n;i++) if (vis[i]){ for (j=0;j<e[i].size();j++){ u=i; v=e[i][j]; if (!vis[v]) continue; u=ff(u); v=ff(v); if (u!=v){ cnt--; fa[u]=v; } } } ans[m]=cnt; for (i=m-1;i>=0;i--){ vis[arr[i]]=true; cnt++; for (j=0;j<e[arr[i]].size();j++){ u=arr[i]; v=e[arr[i]][j]; if (!vis[v]) continue; u=ff(u); v=ff(v); if (u!=v){ cnt--; fa[u]=v; } } ans[i]=cnt; } for (i=0;i<=m;i++) printf("%d\n",ans[i]); return 0; }
来源:https://www.cnblogs.com/Kilo-5723/p/12190175.html