zoukankan      html  css  js  c++  java
  • [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;
    }
  • 相关阅读:
    Fix Installing .NET Framework 3.5 failed Error Code 0x800F0954 on Windows 10
    RHEL8安装五笔输入法
    Enable EPEL and Local Repository on RHEL8
    Why is Yum Replaced by DNF?
    检查Linux服务器是否被攻击的常用命令及方法
    IDEA 主题
    IDEA 如何显示一个类中所有的方法
    Appium 安装以及安装过程中遇到的问题
    Maven 如何发布 jar 包到 Nexus 私库
    java泛型的基本使用
  • 原文地址:https://www.cnblogs.com/zeroform/p/8454841.html
Copyright © 2011-2022 走看看