洛谷 P1197 [JSOI2008]星球大戰(並查集,建圖)
阿新 • • 發佈:2021-09-16
傳送門
解題思路
每次刪邊複雜度太高,所以可以倒序加邊。
注意在對方佔領後,這個點就不參與連通塊數量的計算了。
AC程式碼
#include<iostream> #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> using namespace std; const int maxn=4e5+5; int n,m,k,a[maxn],p[maxn],cnt,num,fa[maxn],ans[maxn],q[maxn],vis[maxn]; struct node{ int v,next; }e[maxn]; void insert(int u,int v){ num++; e[num].v=v; e[num].next=p[u]; p[u]=num; } int find(int x){ return fa[x]=(fa[x]==x?x:find(fa[x]));} int main(){ ios::sync_with_stdio(false); memset(p,-1,sizeof(p)); cin>>n>>m; for(int i=1;i<=n;i++){ fa[i]=i; } for(int i=1;i<=m;i++){ int u,v; cin>>u>>v; insert(u,v); insert(v,u); } cin>>k; for(int i=1;i<=k;i++){ cin>>q[i]; vis[q[i]]=1; } for(int u=0;u<n;u++){ if(!vis[u]){ for(int i=p[u];i!=-1;i=e[i].next){ int v=e[i].v; if(vis[v]) continue; int f1=find(u),f2=find(v); if(f1!=f2){ fa[f1]=f2; cnt++; } } } } ans[k]=n-k-cnt; for(int u=k;u>=1;u--){ vis[q[u]]=0; for(int i=p[q[u]];i!=-1;i=e[i].next){ int v=e[i].v; if(vis[v]) continue; int f1=find(q[u]),f2=find(v); if(f1!=f2){ fa[f1]=f2; cnt++; } } ans[u-1]=n-(u-1)-cnt; } for(int i=0;i<=k;i++) cout<<ans[i]<<endl; return 0; }