zoukankan      html  css  js  c++  java
  • [Luogu 1197] JSOI2008 星球大战

    [Luogu 1197] JSOI2008 星球大战

    <题目链接>


    我算是真的沦为联赛选手了。

    并查集裸题。

    比较麻烦的是删点。

    但是从后往前加点就好操作很多。

    所以考虑离线,先存图,然后没被删的点之间,有边就合并。

    每加一个点进来,把连着这个点且当前没被删的点并进来,更新连通块个数并存入答案。

    最终按顺序输出答案即可。

    #include <cstdio>
    #include <cstring>
    const int MAXN=400010,MAXM=200010;
    bool gone[MAXN];
    int n,m,k,sum,q[MAXN],ans[MAXN];
    struct Edge
    {
    	int to;
    	Edge *next;
    	Edge(int to,Edge* next):to(to),next(next){}
    	~Edge(void)
    	{
    		if(next!=nullptr)
    			delete next;
    	}
    }*head[MAXN];
    class UFS
    {
    	private:
    		bool exist[MAXN];
    		int f[MAXN];
    		int Find(int x)
    		{
    			return x==f[x] ? x : f[x]=Find(f[x]);
    		}
    	public:
    		UFS(int n)
    		{
    			memset(exist,0,sizeof exist);
    			for(int i=0;i<n;++i)
    			{
    				head[i]=nullptr;
    				f[i]=i;
    			}
    		}
    		~UFS(void)
    		{
    			for(int i=0;i<n;++i)
    				delete head[i];
    		}
    		void Merge(int x,int y)
    		{
    			f[Find(y)]=Find(x);
    		}
    		int Count(void)
    		{
    			int ans=0;
    			for(int i=0,t;i<n;++i)
    				if(!gone[i] && !exist[t=Find(i)])
    				{
    					++ans;
    					exist[t]=1;
    				}
    			return ans;
    		}
    		bool Connected(int x,int y)
    		{
    			return Find(x)==Find(y);
    		}
    };
    void AddEdges(int u,int v)
    {
    	head[u]=new Edge(v,head[u]);
    	head[v]=new Edge(u,head[v]);
    }
    int main(int argc,char** argv)
    {
    	scanf("%d %d",&n,&m);
    	static UFS *S=new UFS(n);
    	for(int i=1,x,y;i<=m;++i)
    	{
    		scanf("%d %d",&x,&y);
    		AddEdges(x,y);
    	}
    	scanf("%d",&k);
    	for(int i=1;i<=k;++i)
    	{
    		scanf("%d",&q[i]);
    		gone[q[i]]=true;
    	}
    	for(int u=0;u<n;++u)
    		if(!gone[u])
    			for(Edge *i=head[u];i!=nullptr;i=i->next)
    			{
    				int v=i->to;
    				if(!gone[v])
    					S->Merge(u,v);
    			}
    	ans[k]=sum=S->Count();
    	for(int j=k,u;j>=1;--j)
    	{
    		++sum;
    		gone[u=q[j]]=false;
    		for(Edge *i=head[u];i!=nullptr;i=i->next)
    		{
    			int v=i->to;
    			if(gone[v]==false && !S->Connected(u,v))
    			{
    				--sum;
    				S->Merge(u,v);
    			}
    		}
    		ans[j-1]=sum;
    	}
    	for(int i=0;i<=k;++i)
    		printf("%d
    ",ans[i]);
    	delete S;
    	return 0;
    }
    

    谢谢阅读。

  • 相关阅读:
    【pandas实战】时间差计算
    【pandas实战】数据分类整理
    海量数据处理方法整理记录
    Springboot中实现策略模式+工厂模式
    实现一个秒杀系统
    Redis实现的分布式锁和分布式限流
    实现分布式服务注册及简易的netty聊天
    聊聊数据库乐观锁和悲观锁,乐观锁失败后重试
    聊聊RPC原理二
    聊聊kafka结构
  • 原文地址:https://www.cnblogs.com/Capella/p/9130807.html
Copyright © 2011-2022 走看看