[bzoj1015][JSOI2008]星球大战starwar

来源:互联网 发布:淘宝花呗分期扣全款 编辑:程序博客网 时间:2024/05/27 20:41

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;}
0 0
原创粉丝点击