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

    OJ题号:BZOJ1015、洛谷1197

    思路:并查集。

    将已经合并的结点拆开并不容易,因此可以考虑将此题倒着操作,把不连通的结点合并。

    由题意得总共有n个结点,其中k个结点最终被删除,因此最终剩下的结点为n-k。

    首先对这n-k个结点进行合并操作。然后将删除的点逆序加入图中,同时进行合并操作。每进行一次合法的合并操作就意味着减少一个联通块,同时要注意加入结点时,该结点本身也算一个新的联通块。

    最后按原顺序输出每次的联通块个数。

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<vector>
     4 #include<stack>
     5 const int N=400000;
     6 class UnionFindSet {
     7     private:
     8         int anc[N];
     9         int Find(int x) {
    10             return (x==anc[x])?x:(anc[x]=Find(anc[x]));
    11         }
    12     public:
    13         UnionFindSet(int n) {
    14             for(int i=0;i<n;i++) anc[i]=i;
    15         }
    16         bool isConnected(int x,int y) {
    17             return Find(x)==Find(y);
    18         }
    19         void Union(int x,int y) {
    20             anc[Find(y)]=Find(x);
    21         }
    22 };
    23 int main() {
    24     int n,m;
    25     scanf("%d%d",&n,&m);
    26     std::vector<int> edge[n];
    27     for(int i=0;i<m;i++) {
    28         int x,y;
    29         scanf("%d%d",&x,&y);
    30         edge[x].push_back(y);
    31         edge[y].push_back(x);
    32     }
    33     int k;
    34     scanf("%d",&k);
    35     std::stack<int> attack_list;
    36     bool attacked[n];
    37     memset(attacked,0,sizeof attacked);
    38     for(int i=0;i<k;i++) {
    39         int x;
    40         scanf("%d",&x);
    41         attack_list.push(x);
    42         attacked[x]=true;
    43     }
    44     int ans=0;
    45     UnionFindSet set(n);
    46     for(int i=0;i<n;i++) {
    47         if(!attacked[i]) {
    48             ans++;
    49             for(std::vector<int>::iterator j=edge[i].begin();j<edge[i].end();j++) {
    50                 if(set.isConnected(i,*j)||attacked[*j]) continue;
    51                 set.Union(i,*j);
    52                 ans--;
    53             }
    54         }
    55     }
    56     std::stack<int> answers;
    57     while(!attack_list.empty()) {
    58         answers.push(ans);
    59         ans++;
    60         for(std::vector<int>::iterator i=edge[attack_list.top()].begin();i<edge[attack_list.top()].end();i++) {
    61             if(set.isConnected(attack_list.top(),*i)||attacked[*i]) continue;
    62             set.Union(attack_list.top(),*i);
    63             ans--;
    64         }
    65         attacked[attack_list.top()]=false;
    66         attack_list.pop();
    67     }
    68     answers.push(ans);
    69     while(!answers.empty()) {
    70         printf("%d
    ",answers.top());
    71         answers.pop();
    72     }
    73     return 0;
    74 }
  • 相关阅读:
    利用ArcToolBox ModelBuider进行数据处理
    【转】C#中通过API调用获取文件图标
    【转】利用C#实现标注式消息提示窗口
    【转】在C#2005中创建快捷方式
    爱一个人好难
    【转】C#获取文件与文件夹默认图标
    【转】远程教育理论中几个基本概念的探讨2
    【转】C#中Bitmap类实现对图像操作的一些方法
    【转】C#启动外部程序
    WshShortcut 对象说明
  • 原文地址:https://www.cnblogs.com/skylee03/p/6973511.html
Copyright © 2011-2022 走看看