zoukankan      html  css  js  c++  java
  • UVALive 6910 Cutting Tree(离线逆序并查集)

    【题目】:(地址:)

    http://acm.hust.edu.cn/vjudge/contest/view.action?cid=97671#problem/E

    【题意】:

    给出多棵树和两类操作:操作(C  x)删除结点 x 与其父结点的连边;操作(Q a b)询问 a b 是否连通。

    【解题思路】:

    连通性的查询容易想到用并查集,关键在于如何处理删边。

    考虑到删边的难点在于查询时的路径压缩导致某些结点与其父结点"不直接相连",这里使用离线处理,在查询之前把所有该删的边删除,同时逆序处理询问操作;当逆序处理到删边操作时,复原删掉的边(删除变为增边)。

    【代码】:(上了个比较标准的并查集模板)

      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cstring>
      4 #include<cmath>
      5 #include<stack>
      6 #include<algorithm>
      7 #define LL long long
      8 #define maxn 25000
      9 #define IN freopen("in.txt","r",stdin);
     10 using namespace std;
     11 
     12 
     13 struct Union_Find_Set{
     14 
     15     int fa[maxn];    /*每个结点的父亲节点编号*/
     16     int rank[maxn];    /*树的高度*/
     17 
     18     /*构造并查集并初始化*/
     19     void make_set()
     20     {
     21         for(int i=0; i<maxn; i++){
     22             fa[i] = i;    /*初始时本身构成一个集合,根为本身*/
     23             rank[i] = 0;
     24         }
     25     }
     26 
     27     /*递归查找结点所在树的根节点*/
     28     int find_set(int x)
     29     {
     30         /*路径压缩*/
     31         return x!=fa[x]? fa[x]=find_set(fa[x]) : x;
     32     }
     33 
     34     /*合并两个集合*/
     35     void unite_set(int x, int y)
     36     {
     37         x = find_set(x);
     38         y = find_set(y);
     39         /*记录树的高度防止合并后退化,rank小的向rank大的连接*/
     40         if(rank[x] < rank[y]) swap(x,y);
     41         fa[y] = x;    /*合并*/
     42         if(rank[x] == rank[y]) rank[x]++;    /*高度相同则加1*/
     43     }
     44 
     45     /*判断两结点是否属于同一集合*/
     46     bool same_set(int x, int y)
     47     {
     48         return find_set(x) == find_set(y);
     49     }
     50 }UFS;
     51 
     52 int n,q;
     53 struct node{
     54     char type;
     55     int first, second;
     56 };
     57 
     58 stack<node> s;
     59 stack<bool> ans;
     60 
     61 int main(int argc, char const *argv[])
     62 {
     63     //IN;
     64 
     65     int t,ca=1;scanf("%d",&t);
     66     while(t--)
     67     {
     68         scanf("%d %d",&n,&q);
     69 
     70         while(!s.empty()) s.pop();
     71         while(!ans.empty()) ans.pop();
     72         UFS.make_set();
     73 
     74         for(int i=1; i<=n; i++){
     75             scanf("%d",&UFS.fa[i]);
     76             if(!UFS.fa[i]) UFS.fa[i] = i;
     77         }
     78 
     79         for(int i=1; i<=q; i++)
     80         {
     81             node tmp_node;
     82             getchar();
     83             scanf("%c",&tmp_node.type);
     84             if(tmp_node.type=='Q'){
     85                 scanf("%d %d",&tmp_node.first, &tmp_node.second);
     86             }
     87             else{
     88                 scanf("%d",&tmp_node.first);
     89                 tmp_node.second = UFS.fa[tmp_node.first];
     90                 /*离线处理--询问之前删边,避免路径压缩导致删边失效*/
     91                 UFS.fa[tmp_node.first] = tmp_node.first;
     92             }
     93             s.push(tmp_node);
     94         }
     95 
     96         while(q--)
     97         {
     98             node tmp_node = s.top(); s.pop();
     99 
    100             if(tmp_node.type=='Q'){
    101                 if(UFS.same_set(tmp_node.first, tmp_node.second)) ans.push(1);
    102                 else ans.push(0);
    103             }
    104             else{
    105                 UFS.fa[tmp_node.first] = tmp_node.second;
    106             }
    107         }
    108 
    109         printf("Case #%d:
    ", ca++);
    110         while(!ans.empty())
    111         {
    112             if(ans.top() == 1) puts("YES");
    113             else puts("NO");
    114             ans.pop();
    115         }
    116     }
    117 
    118     return 0;
    119 }
  • 相关阅读:
    机器学习笔记之K近邻算法
    [C++基础]在子类中向父类的构造函数传递参数的小例子,包括类中常量的初始化
    POJ2709 染料贪心
    POJ2337 欧拉路径字典序输出
    POJ2337 欧拉路径字典序输出
    POJ1042 贪心钓鱼
    POJ3228二分最大流
    POJ3228二分最大流
    POJ3498最大流,枚举终点,企鹅,基础最大流
    POJ3498最大流,枚举终点,企鹅,基础最大流
  • 原文地址:https://www.cnblogs.com/Sunshine-tcf/p/4960057.html
Copyright © 2011-2022 走看看