zoukankan      html  css  js  c++  java
  • BZOJ 1015 [JSOI2008]星球大战starwar (逆序并查集)

    BZOJ 1015

    思路:并查集只有联边的作用,无法做到拆边,因此采取逆序做法。先将边拆掉,再用并查集进行联边,不同联通块相连则联通块数目减一。

     1 #include<bits/stdc++.h>
     2 #define se second
     3 #define fi first
     4 #define ll long long
     5 #define ls l,m,rt<<1
     6 #define rs m+1,r,rt<<1|1
     7 #define Pii pair<int,int>
     8 #define pb push_back
     9 #define fio ios::sync_with_stdio(false);cin.tie(0)
    10 using namespace std;
    11 const double pi=acos(-1.0);
    12 const int N=1e6+5;
    13 using namespace std;
    14 int fa[N];
    15 int tot;
    16 struct node{
    17     int u,v;
    18 }q[200010];
    19 int a[N];
    20 bool vis[N];
    21 int ans[N];
    22 vector<int>un[N];
    23 void init (int x){
    24     for(int i=0;i<=x;i++){
    25         fa[i]=i;
    26     }
    27 }
    28 int findfa(int x){
    29     return fa[x]==x?x:fa[x]=findfa(fa[x]);
    30 }
    31 void unite(int x,int y){
    32     x=findfa(x);
    33     y=findfa(y);
    34     if(x!=y){
    35         fa[y]=x;
    36         tot--;//不同联通块相连则联通块数目减一
    37     }
    38 }
    39 
    40 int main(){
    41     int n,m;
    42     scanf("%d %d",&n,&m);
    43     init(n);
    44     for(int i=0;i<m;i++){
    45         scanf("%d %d",&q[i].u,&q[i].v);
    46     }
    47     int k;
    48     scanf("%d",&k);
    49     for(int i=1;i<=k;i++){
    50         scanf("%d",&a[i]);
    51         vis[a[i]]=1;
    52     }
    53     tot=n-k;
    54     for(int i=0;i<m;i++){
    55         if(vis[q[i].u]||vis[q[i].v]){// 如果一边是被拆掉的,则将两个点互相对方的不可行数组中(双向存边),否则直接联边
    56             un[q[i].u].pb(q[i].v);
    57             un[q[i].v].pb(q[i].u);
    58         }
    59         else {
    60             unite(q[i].u,q[i].v);
    61         }
    62     }
    63     ans[k+1]=tot;
    64     for(int i=k;i>0;i--){
    65         tot++;//将该点设为未被打击点,并将联通块加一,因为多出来一个未被打击的联通块
    66         int m=a[i];
    67         vis[m]=0;
    68         for(int j=0;j<un[m].size();j++){
    69             if(!vis[un[m][j]])
    70                 unite(m,un[m][j]);
    71         }
    72         ans[i]=tot;
    73     }
    74     for(int i=1;i<=k+1;i++)printf("%d
    ",ans[i]);
    75     return 0;
    76 }
  • 相关阅读:
    fiddler配置及使用教程
    获取字符串中出现次数最少的字符
    引用数据类型的深拷贝
    jquery一些方法
    常用字体
    图片模拟
    返回上一页并刷新
    移动端网页调试神器
    input一些限制
    使用transform后z-index失效的解决方法
  • 原文地址:https://www.cnblogs.com/Mrleon/p/8401412.html
Copyright © 2011-2022 走看看