Sample Input
8 13 0 1 1 6 6 5 5 0 0 6 1 2 2 3 3 4 4 5 7 1 7 2 7 6 3 6 5 1 6 3 5
Sample Output
1 1 1 2 3 3
#include <bits/stdc++.h> using namespace std; int tot,n,m,d,f[400001],head[400001],q[400001],ans[400001],cnt=1; bool used[400001], des[400001]; struct data{int to,next;}e[400001]; //next是 int find(int x){return x==f[x]?x:f[x]=find(f[x]);} void ins(int u,int v) {//存图 e[++cnt].to=u; e[cnt].next=head[v]; head[v]=cnt; e[++cnt].to=v; e[cnt].next=head[u]; head[u]=cnt; } void add(int x) { int i=head[x],p=find(x),q; //p是x的父节点, while(i) { if(used[e[i].to]) { // 如果该点被使用过 q=find(e[i].to); //q就为e[i].to的父节点 if(p!=q){f[q]=p;tot--;} //如果两个父节点不同(不是它本身) p为q的父节点 tot自减 } i=e[i].next; //i为与它相邻的点 } } int main() { scanf("%d%d",&n,&m); for(int i=0;i<n;i++) f[i]=i; for(int i=1;i<=m;i++) { int x,y; scanf("%d%d",&x,&y); ins(x,y); } scanf("%d",&d); // d是进行的操作次数 for(int i=1;i<=d;i++) { scanf("%d",&q[i]); des[q[i]]=1; // 记录被摧毁的星球 } for(int i=0;i<n;i++) { if(!des[i]) { //如果该星球没有被摧毁 tot++; //记录没有被摧毁的星球个数 add(i); //传入add函数(即merge函数进行并查集构图 used[i]=1; //i已经进入图中 } } ans[d+1]=tot; //此时tot是除去被摧毁星球的连通块数目 for(int i=d;i>0;i--) { tot++; // 摧毁一个星球首先默认会导致连通块++ add(q[i]); //将被摧毁的星球补回去 used[q[i]]=1; //q[i]被使用 ans[i]=tot; // tot此时为该状态下的连通块数 } for(int i=1;i<=d+1;i++)printf("%d\n",ans[i]); return 0; }
原文地址:https://www.cnblogs.com/lightac/p/10721378.html
时间: 2024-11-09 00:59:07