zoukankan      html  css  js  c++  java
  • 洛谷 P1197 [JSOI2008]星球大战

    题意简述

    有n个点和m条通道,
    现在按顺序破坏k个点
    求每一次破坏后联通块的个数

    题解思路

    并查集,逆序做,
    先假设给的k个星球全都被炸,求出此时的联通块个数,就是经过k次打击的联通块个数。
    然后每次加上一个被炸的星球,就求出了经过每次次打击后的联通块个数

    代码

    #include <cstdio>
    using namespace std;
    int n, m, k, u, v, cnt, sum, x, y;
    int d[401000], fa[401000], ans[401000];
    int f[401000], to[801000], nxt[801000];
    bool bd[401000];
    void add_edge(int u, int v)
    {
    	to[++cnt] = v;
    	nxt[cnt] = f[u];
    	f[u] = cnt;
    }
    int gf(int x)
    {
    	return x == fa[x] ? x : fa[x] = gf(fa[x]);
    }
    int main()
    {
    	scanf("%d%d", &n, &m);
    	for (register int i = 1; i <= m; ++i)
    	{
    		scanf("%d%d", &u, &v);
    		add_edge(u, v);
    		add_edge(v, u);
    	}
    	for (register int i = 0; i < n; ++i) fa[i] = i;
    	scanf("%d", &k);
    	for (register int i = 1; i <= k; ++i)
    	{
    		scanf("%d", &d[i]);
    		bd[d[i]] = 1;
    	}
    	sum = n - k;
    	for (register int i = 0; i < n; ++i)
    		if (!bd[i])
    			for (register int j = f[i]; j; j = nxt[j])
    				if (!bd[to[j]])
    				{
    					x = gf(i);
    					y = gf(to[j]);
    					if (x != y)
    					{
    						fa[y] = x;
    						--sum;
    					}
    				}
    	ans[k + 1] = sum;
    	for (register int i = k; i; --i)
    	{
    		++sum;
    		bd[d[i]] = 0;
    		x = gf(d[i]);
    		for (register int j = f[d[i]]; j; j = nxt[j])
    			if (!bd[to[j]])
    			{
    				y = gf(to[j]);
    				if (x != y)
    				{
    					fa[y] = x;
    					--sum;
    				}
    			}
    		ans[i] = sum;
    	}
    	for (register int i = 1; i <= k + 1; ++i) printf("%d
    ", ans[i]);
    }
    
  • 相关阅读:
    CentOS 出错处理
    g13 root
    修复误删系统文件
    c++ list sort方法
    批量修改outlook联系人头像,并同步手机
    IT大牛们 学术搜索
    oracle 表空间操作
    CentOS 5.5 安装MPICH2\MRNet\Launchmon时遇到的问题
    自我反省
    积累航程
  • 原文地址:https://www.cnblogs.com/xuyixuan/p/9594419.html
Copyright © 2011-2022 走看看