19号学校要考试了,检测大家寒假预习情况…… 题目大意:一个无向图上有N个点,有m条边,要按顺序删点,按次序输出每次删点后图中的连通块数量。 因为删点的操作实现过于复杂,所以我们可以考虑倒着来将一个个点加入图中,通过并查集来求出连通块数量。
#include <cstdio>#include <vector>using namespace std;#define rover 10000inline char tc(void){ static char fl[rover+1],*A=fl,*B=fl; return A==B?B=(A=fl)+fread(fl,1,rover,stdin),A==B?EOF:*A++:*A++;}#define C (c=tc())inline void read(int &a){ a=0;static char c; int f=1; while(C<'0'||c>'9') c=='-'?f=-1:0; while(c>='0'&&c<='9') a=a*10+c-'0',C; a*=f; return ;}int n,m,x,y,k,od[400002],f[400002],tot,sum,ans[400002];vector<int> s[400002];bool b[400002];int gf(int x){ return x==f[x]?x:f[x]=gf(f[x]);}int main(void){ register int i,j; read(n),read(m); for (i=0;i<n;++i) f[i]=i; for (i=1;i<=m;++i) read(x),read(y),s[x].push_back(y),s[y].push_back(x); read(k); for (i=1;i<=k;++i) read(od[i]),b[od[i]]=1; for (i=0;i<n;++i) if(b[i]==0) { ++sum; for (j=0;j<s[i].size();++j) if(b[s[i][j]]==0&&gf(i)!=gf(s[i][j])) --sum,f[f[i]]=f[s[i][j]]; } ans[tot=k+1]=sum; while(k) { ++sum; b[od[k]]=0; for (j=0;j<s[od[k]].size();++j) if(b[s[od[k]][j]]==0&&gf(od[k])!=gf(s[od[k]][j])) --sum,f[f[od[k]]]=f[s[od[k]][j]]; ans[k]=sum; --k; } for (i=1;i<=tot;++i) PRintf("%d/n",ans[i]); return 0;}新闻热点
疑难解答