• [JSOI2008]星球大战


    原题链接:https://www.luogu.org/problemnew/show/P1197

    题意简述:给出n个点的无向图,每次删去一个点,询问当前的连通块个数。

    删点太难做,不如加点,首先将询问读取,然后离线倒着处理。

    标记每个已经删去的点,首先计算出所有没标记的点一共组成多少个连通块。

    然后依次加点,同时删去标记,首先将连通块个数增加1,而当前点每与其他的连通块相连,连通块个数减少1,最终算出答案即可

    能够保证每条边最多走两遍,并查集时间复杂度不计的话,时间复杂度O(n)

    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    using namespace std;
    void read(int &y)
    {
        y=0;char x=getchar();
        while(x<'0'||x>'9') x=getchar();
        while(x>='0'&&x<='9')
        {
            y=y*10+x-'0';
            x=getchar();
        }
    }
    int n,m,cnt,ans;
    int f[400005],head[400005];
    int q[200005],vis[400005];
    struct edge
    {
        int u,v;
    }e[400005];
    void add(int u,int v)
    {
        e[++cnt].u=head[u];
        e[cnt].v=v;
        head[u]=cnt;
    }
    int find(int x)
    {
        if(x==f[x]) return x;
        return f[x]=find(f[x]);
    }
    int main()
    {
        int u,v;
        read(n);read(m);
        for(int i=1;i<n;i++) f[i]=i;
        memset(head,-1,sizeof(head));
        for(int i=0;i<m;i++)
        {
            read(u);read(v);
            add(u,v);add(v,u);
        }
        read(m);
        for(int i=0;i<m;i++)
        {
            read(q[i]);
            vis[q[i]]=1;
        }
        ans=n-m;
        for(int i=0;i<n;i++)
        {
            if(vis[i]==1) continue;
            for(int j=head[i];j!=-1;j=e[j].u)
            {
                if(vis[e[j].v]==1) continue;
                u=find(i);
                v=find(e[j].v);
                if(u==v) continue;
                f[v]=u;
                ans--;
            }
        }
        q[m]=ans;
        for(int i=m-1;i>=0;i--)
        {
            vis[q[i]]=0;
            int tans=-1;
            for(int j=head[q[i]];j!=-1;j=e[j].u)
            {
                if(vis[e[j].v]==1) continue;
                u=find(q[i]);
                v=find(e[j].v);
                if(u==v) continue;
                f[u]=v;
                tans++;
            }
            q[i]=q[i+1]-tans;
        }
        for(int i=0;i<=m;i++) printf("%d
    ",q[i]);
        return 0;
    }
  • 相关阅读:
    bzoj 2618: [Cqoi2006]凸多边形
    BZOJ 4556 [Tjoi2016&Heoi2016]字符串
    BZOJ 4850 [Jsoi2016]灯塔
    BZOJ 2956: 模积和
    PHP 正则表达式
    Linux Centos6.5安装redis3.0 和phpredis
    linux 删除过期文件
    THINKPHP报错 _STORAGE_WRITE_ERROR
    THINKPHP 部署nginx上URL 构造错误
    Linux 修改mysql密码
  • 原文地址:https://www.cnblogs.com/zeroform/p/8454841.html
Copyright © 2020-2023  润新知