码迷,mamicode.com
首页 > 其他好文 > 详细

BZOJ 4668: 冷战

时间:2016-12-23 22:47:19      阅读:221      评论:0      收藏:0      [点我收藏+]

标签:printf   rip   else   ret   ace   space   pre   des   name   

Description

在一个图上,在两个点间连一条边,问这两个点最早在什么时候联通.

Sol

并查集+启发式合并.

按秩合并的并查集...我也不知道什么是按秩合并,反正就跟启发式合并差不多,合并的时候将小的往大的里和,因为每次增长都是小集合倍数的两倍以上,所以层数不超过 \(log n\)

然后连边的时候记录一下是第几次连接的,统计一下深度,最后暴力找LCA...

Code

/**************************************************************
    Problem: 4668
    User: BeiYu
    Language: C++
    Result: Accepted
    Time:1256 ms
    Memory:9104 kb
****************************************************************/
 
#include <bits/stdc++.h>
using namespace std;
 
const int N = 5e5+50;
 
int n,lst;
struct UnionTable {
    int f[N],s[N],v[N],d[N];
    void init(int n) {
        for(int i=1;i<=n;i++) f[i]=i,v[i]=0,s[i]=1;
    }
    int find(int x) {
        if(f[x]^x) {
            int fa=find(f[x]);
            d[x]=d[f[x]]+1;
            return fa;
        }else return x;
    }
    void Union(int x,int y,int c) {
        int f1=find(x),f2=find(y);
        if(f1==f2) return;
        if(s[f1]>s[f2]) f[f2]=f1,v[f2]=c,s[f1]+=s[f2];
        else f[f1]=f2,v[f1]=c,s[f2]+=s[f1];
    }
    int Query(int x,int y) {
        int f1=find(x),f2=find(y),r=0;
        if(f1!=f2) return 0;
        for(;x^y;) {
            if(d[x]<d[y]) swap(x,y);
            r=max(r,v[x]),x=f[x];
        }return r;
    }
}un;
 
 
inline int in(int x=0,char ch=getchar()) { while(ch>‘9‘ || ch<‘0‘) ch=getchar();
    while(ch>=‘0‘ && ch<=‘9‘) x=x*10+ch-‘0‘,ch=getchar();return x; }
int main() {
    n=in();
    un.init(n);
    for(int m=in(),c=0;m--;) {
        int opt=in(),u=in()^lst,v=in()^lst;
        if(!opt) un.Union(u,v,++c);
        else printf("%d\n",lst=un.Query(u,v));
    }return 0;
}

 

BZOJ 4668: 冷战

标签:printf   rip   else   ret   ace   space   pre   des   name   

原文地址:http://www.cnblogs.com/beiyuoi/p/6216153.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!