• BZOJ 4668 冷战(按秩合并并查集+LCA)


    4668: 冷战

    Time Limit: 10 Sec  Memory Limit: 256 MB
    Submit: 627  Solved: 303
    [Submit][Status][Discuss]

    Description

    1946 年 3 月 5 日,英国前首相温斯顿·丘吉尔在美国富尔顿发表“铁
    幕演说”,正式拉开了冷战序幕。
    美国和苏联同为世界上的“超级大国”,为了争夺世界霸权,两国及其
    盟国展开了数十年的斗争。在这段时期,虽然分歧和冲突严重,但双方都
    尽力避免世界范围的大规模战争(第三次世界大战)爆发,其对抗通常通
    过局部代理战争、科技和军备竞赛、太空竞争、外交竞争等“冷”方式进
    行,即“相互遏制,不动武力”,因此称之为“冷战”。
    Reddington 是美国的海军上将。由于战争局势十分紧张,因此他需要
    时刻关注着苏联的各个活动,避免使自己的国家陷入困境。苏联在全球拥
    有 N 个军工厂,但由于规划不当,一开始这些军工厂之间是不存在铁路
    的,为了使武器制造更快,苏联决定修建若干条道路使得某些军工厂联通。
    Reddington 得到了苏联的修建日程表,并且他需要时刻关注着某两个军工
    厂是否联通,以及最早在修建哪条道路时会联通。具体而言,现在总共有
    M 个操作,操作分为两类:
    • 0 u v,这次操作苏联会修建一条连接 u 号军工厂及 v 号军工厂的铁
    路,注意铁路都是双向的;
    • 1 u v, Reddington 需要知道 u 号军工厂及 v 号军工厂最早在加入第
    几条条铁路后会联通,假如到这次操作都没有联通,则输出 0;
    作为美国最强科学家, Reddington 需要你帮忙设计一个程序,能满足
    他的要求。

    Input

    第一行两个整数 N, M。
    接下来 M 行,每行为 0 u v 或 1 u v 的形式。
    数据是经过加密的,对于每次加边或询问,真正的 u, v 都等于读入的
    u, v 异或上上一次询问的答案。一开始这个值为 0。
    1 ≤ N, M ≤ 500000,解密后的 u, v 满足1 ≤ u, v ≤ N, u不等于v

    Output

    对于每次 1 操作,输出 u, v 最早在加入哪条边后会联通,若到这个操
    作时还没联通,则输出 0。

    Sample Input

    5 9
    0 1 4
    1 2 5
    0 2 4
    0 3 4
    1 3 1
    0 7 0
    0 6 1
    0 1 6
    1 2 6

    Sample Output

    0
    3
    5

    题解

    因为边建在一个联通块里并没有什么用可以忽略,也就是说是一个树形的结构
    所以直接上裸的按秩合并并查集
    记录当前点到父亲的边权,查询时,求LCA过程中顺便可以求出路径最大值。
     1 #include<iostream>
     2 #include<cstring>
     3 #include<cstdio>
     4 #include<cmath>
     5 #include<algorithm>
     6 using namespace std;
     7 const int N=501000;
     8 int fa[N],dep[N],size[N],w[N],ans,m,n,tot;
     9 int find(int x){
    10     if(fa[x]==x)return x;
    11     int y=find(fa[x]);
    12     dep[x]=dep[fa[x]]+1;
    13     return y;
    14 }
    15 void getlca(int x,int y){
    16     while(x!=y){
    17         if(dep[x]<dep[y])swap(x,y);
    18         ans=max(ans,w[x]);
    19         x=fa[x]; 
    20     }
    21 }
    22 int main(){
    23     scanf("%d%d",&n,&m);
    24     for(int i=1;i<=n;i++)fa[i]=i,size[i]=1;
    25     while(m--){
    26         int k;
    27         scanf("%d",&k);
    28         if(k==0){
    29             int x,y;
    30             scanf("%d%d",&x,&y);
    31             x^=ans;y^=ans;
    32             int a=find(x);int b=find(y);
    33             if(a==b){
    34                 tot++;
    35                 continue;
    36             }
    37             else{
    38                 if(size[a]>size[b]){
    39                     size[a]+=size[b];
    40                     fa[b]=a;
    41                     w[b]=++tot;
    42                 }
    43                 else{
    44                     size[b]+=size[a];
    45                     fa[a]=b;
    46                     w[a]=++tot;
    47                 }
    48             }
    49         }
    50         else{
    51             int x,y;
    52             scanf("%d%d",&x,&y);
    53             x^=ans;y^=ans; 
    54             ans=0;
    55             int a=find(x);int b=find(y);
    56             if(a!=b){
    57                 printf("0
    ");
    58                 continue;
    59             }
    60             getlca(x,y);
    61             printf("%d
    ",ans);
    62         }
    63     }
    64     return 0;
    65 }
  • 相关阅读:
    Hashcode的作用
    java 强弱软虚 四种引用,以及用到的场景
    Object类有哪些公用方法?
    equals和==的区别
    switch能否用string做参数
    Java九种基本数据类型,以及他们的封装类
    Singleton(Java)
    快速排序和二分查找(Javascript)
    快速排序和二分查找(Go)
    ubuntn 安装 MySQL
  • 原文地址:https://www.cnblogs.com/Xu-daxia/p/9562500.html
Copyright © 2020-2023  润新知