// 此博文为迁移而来,写于2015年7月16日,不代表本人现在的观点与看法。原始地址:http://blog.sina.com.cn/s/blog_6022c4720102w6le.html

1、题目

【P.S. BZOJ上的题面问题很多,这里进行了一些修改和简化】

 
2、TAG

JSOI2008江苏省队选拔题;并查集。

3、分析
       作为一道省队选拔题确实感觉有点水水的。可能唯一难点在于难以想到这种方式。由题意,我们先可以想出一种最暴力的做法——对于每次的摧毁,跑一遍DFS判断连通块个数。然而这速度也是极慢的。
       可以这样想:一个星球与其他若干星球相连,则它们必定属于一个连通块;如果将其摧毁,即相当于将所有与其相连的星球拆开,不再属于同一个连通块。但是这样的话,我们难以判断某两个星球它们是不是存在除经过该星球的其他连通路径。
       所以我们可以反过来思考——首先我们将所有要摧毁的星球摧毁,计算出最后时刻的连通块个数,然后我们根据题目所给顺序反着对其进行加点,每一次的添加星球,都是将所有与其相连的星球并入同一个连通块。这样,我们就不需要考虑他们之前的状态了。并入的过程用并查集完成即可。
        
4、代码
---------------------------------------------------------------------------------------------------

#include<cstdio>
#include<cstring>
#define MAXN 400005

struct Edge
{
        int v,next,flag;
};
Edge edge[MAXN];

int vis[MAXN],now=1,h[MAXN],n,m,v,u,p[MAXN],k,tot,set[MAXN],ans[MAXN],flag[MAXN],del[MAXN];

void addEdge(int u,int v)
{
        now++;
        edge[now].v=v;
        edge[now].next=h[u];
        h[u]=now;
}

int check(int x)
{
        if (set[x]==x) return x;
        return (set[x]=check(set[x]));
}

void DFS(int now,int nowFa)
{
        for (int x=h[now];x!=-1;x=edge[x].next) 
         if (!vis[edge[x].v]) { vis[edge[x].v]=1; set[check(now)]=check(edge[x].v); DFS(edge[x].v,nowFa); }
        return;
}

void init()
{
        memset(h,-1,sizeof(h));
        scanf("%d %d",&n,&m);
        for (int i=1;i<=m;i++) 
        {
                scanf("%d %d",&u,&v);
                addEdge(u,v),addEdge(v,u);
        }
        scanf("%d",&k);
        for (int i=1;i<=k;i++) 
        {
                scanf("%d",&p[i]);
                vis[p[i]]=1;
                del[p[i]]=1;
        }
        for (int i=0;i<=n-1;i++) set[i]=i;
        for (int i=0;i<=n-1;i++) if (!vis[i]) { DFS(i,i); tot++; }
}

int main()
{
        init();
        int temp=tot;
        for (int i=k;i>=1;i--)
        {
                del[p[i]]=0; tot++;
                for (int x=h[p[i]];x!=-1;x=edge[x].next)
                {   
                        if (del[edge[x].v]) continue;
                        int v1=check(p[i]),v2=check(edge[x].v);
                        if (v1!=v2) { set[v1]=v2; tot--; }
                }
                ans[i]=tot;
        }
        for (int i=1;i<=k;i++) printf("%d\n",ans[i]);
        printf("%d",tot);
        return 0;
}
---------------------------------------------------------------------------------------------------

[BZOJ1015/JSOI2008]星球大战的更多相关文章

  1. BZOJ1015[JSOI2008]星球大战starwar[并查集]

    1015: [JSOI2008]星球大战starwar Time Limit: 3 Sec  Memory Limit: 162 MBSubmit: 5253  Solved: 2395[Submit ...

  2. BZOJ1015 [JSOI2008]星球大战starwar(并查集)

    1015: [JSOI2008]星球大战starwar Time Limit: 3 Sec  Memory Limit: 162 MBSubmit: 3895  Solved: 1750[Submit ...

  3. [Bzoj1015][JSOI2008]星球大战starwar(并查集)(离线处理)

    1015: [JSOI2008]星球大战starwar Time Limit: 3 Sec  Memory Limit: 162 MBSubmit: 6849  Solved: 3204[Submit ...

  4. BZOJ1015 [JSOI2008]星球大战starwar

    Description 很久以前,在一个遥远的星系,一个黑暗的帝国靠着它的超级武器统治者整个星系.某一天,凭着一个偶然的 机遇,一支反抗军摧毁了帝国的超级武器,并攻下了星系中几乎所有的星球.这些星球通 ...

  5. [洛谷P1197/BZOJ1015][JSOI2008]星球大战Starwar - 并查集,离线,联通块

    Description 很久以前,在一个遥远的星系,一个黑暗的帝国靠着它的超级武器统治者整个星系.某一天,凭着一个偶然的机遇,一支反抗军摧毁了帝国的超级武器,并攻下了星系中几乎所有的星球.这些星球通过 ...

  6. 2018.09.26 bzoj1015: [JSOI2008]星球大战starwar(并查集)

    传送门 并查集经典题目. 传统题都是把删边变成倒着加边,这道题是需要倒着加点. 处理方法是将每个点与其他点的边用一个vector存起来,加点时用并查集统计答案就行了. 代码: #include< ...

  7. [bzoj1015](JSOI2008)星球大战 starwar(离线+并查集)

    Description 很久以前,在一个遥远的星系,一个黑暗的帝国靠着它的超级武 器统治者整个星系.某一天,凭着一个偶然的机遇,一支反抗军摧毁了帝国的超级武器,并攻下了星系中几乎所有的星球.这些星球通 ...

  8. BZOJ1015: [JSOI2008]星球大战starwar【并查集】【傻逼题】

    Description 很久以前,在一个遥远的星系,一个黑暗的帝国靠着它的超级武器统治者整个星系.某一天,凭着一个偶然的机遇,一支反抗军摧毁了帝国的超级武器,并攻下了星系中几乎所有的星球.这些星球通过 ...

  9. bzoj1015: [JSOI2008]星球大战starwar 并查集+离线处理

    题目传送门 这道题可以改为离线处理 倒着找答案 这样删点就变成加点了 有了这个思想题目就很好写了哇 23333 #include<cstdio> #include<cstring&g ...

随机推荐

  1. excel中统计列中的值在其他列出现的次数多个条件

    excel中统计列中的值在其他列出现的次数多个条件 =COUNTIFS(E2:E373,"=VIP经销商",J2:J373,K2) 解释 E列的第二行到第373行中值 等于 VIP ...

  2. WebUploader 上传文件 错误总结

    近日做文件上传,粗心的问题和技术不精的问题导致了很多的bug,大部分时间都是在找自己写出来的bug,近日总结一下使用 WebUploader 开启分片上传的使用方法以及注意事项 1.上传过程中,后续上 ...

  3. C# winform 启动外部程序

    //class里面放入这段代码[DllImport("shell32.dll")]public static extern int ShellExecute(IntPtr hwnd ...

  4. 深入解析 Go 中 Slice 底层实现

    原文: https://halfrost.com/go_slice/   切片是 Go 中的一种基本的数据结构,使用这种结构可以用来管理数据集合.切片的设计想法是由动态数组概念而来,为了开发者可以更加 ...

  5. 【转载】C#的ArrayList使用Contains方法判断是否包含某个元素

    在C#的编程开发中,ArrayList集合是一个常用的非泛型类集合,在ArrayList集合中可以使用Contains方法判断是否包含某个元素数据,如果包含则返回true,否则返回false,Cont ...

  6. Delphi中窗体的事件

    Delphi中窗体的事件 Form窗体可以响应各种各样的时间,在Object Inspector的Events页面中罗列了一大堆,如下图: 下面将要列出一些常用的事件. 1.OnActivate 当窗 ...

  7. Windows 10 蓝牙管理页面"添加蓝牙或其他设备"选项点击无响应的解决方案

    解决方案1(简单,但不解决根本问题): 通过"控制面板→设备和打印机→添加设备"进行添加. 解决方案2: 造成这种现象的原因应该是因为启用了 Administrator 账户,在其 ...

  8. Android viewPager+fragment实现滑页效果

    先上图,手指在手机向左或者向右滑就可以实现相应的页面切换. 先看activity_main.xml文件,非常简单,主要是三个标题TextView和viewpager <?xml version= ...

  9. Java 8 Time Api 使用指南-珍藏限量版

    前面写过了Stream和Lambda,最近正想写Java 8的Time Api,小胖哥这个文章写得很好,就偷懒转载了. 1.概述 Java 8为Date和Time引入了新的API,以解决旧java.u ...

  10. OEL7.6源码安装MYSQL5.7

    首先官网下载安装包https://dev.mysql.com/downloads/mysql/5.7.html#downloads 然后上传解压至/usr/local目录 [root@localhos ...