首页 > 代码库 > 【并查集】BZOJ4668-冷战

【并查集】BZOJ4668-冷战

【题目大意】

给出N个军工厂和M 个操作,操作分为两类:
• 0 u v,这次操作苏联会修建一条连接 u 号军工厂及 v 号军工厂的铁路,注意铁路都是双向的;
• 1 u v, Reddington 需要知道 u 号军工厂及 v 号军工厂最早在加入第几条条铁路后会联通,假如到这次操作都没有联通,则输出 0。
 
【思路】
一开始看到过去状态第一反应可持久化,随即觉得自己简直蠢。
普通的并查集,每次还要记录下t[u],t[u]表示u号军工厂和它的父亲是什么时候连接上的。那么对于u和v,如果它们连通,那么就是u->lca(u,v)->v这条路径上t[u]的最大值。
 
【错误点】
我居然一开始写了u->fa[u]->v…其实lca就可以了啦,lca不一定是最终的父亲。
  1 #include<iostream>  2 #include<cstdio>  3 #include<cstring>  4 #include<algorithm>  5 using namespace std;  6 const int MAXN=500000+50;  7 int u[MAXN],h[MAXN],t[MAXN];  8 int dep[MAXN];  9 int tim; 10 int ans=0,preans=0,n,m; 11  12 int find(int x) 13 { 14     while (x!=u[x])    x=u[x]; 15     return x; 16 } 17  18 void getdep(int x) 19 { 20     if (u[x]==x)  21     { 22         dep[x]=0; 23         return; 24     } 25     else getdep(u[x]); 26     dep[x]=dep[u[x]]+1; 27 } 28  29 int ask(int x,int y) 30 { 31     int ret=-1; 32     getdep(x); 33     getdep(y); 34     if (dep[x]<dep[y]) swap(x,y); 35     while (dep[x]>dep[y]) 36     { 37         ret=max(ret,t[x]); 38         x=u[x]; 39     } 40     while (x!=y) 41     { 42         ret=max(ret,max(t[x],t[y])); 43         x=u[x]; 44         y=u[y]; 45     } 46     return ret; 47 } 48  49 void mintime(int a,int b) 50 { 51     int fa=find(a),fb=find(b); 52     if (fa!=fb) ans=0; 53         else ans=ask(a,b); 54     printf("%d\n",ans); 55     preans=ans; 56 } 57  58 void union_set(int a,int b) 59 { 60     ++tim; 61     int fa=find(a),fb=find(b); 62     if (fa!=fb) 63     {  64         if (h[fa]>h[fb]) 65         { 66             t[fb]=tim; 67             u[fb]=fa; 68         } 69         else 70         { 71             t[fa]=tim; 72             u[fa]=fb; 73             if (h[fa]==h[fb]) ++h[fb]; 74         } 75     } 76 } 77  78 void init() 79 { 80     memset(dep,0,sizeof(dep)); 81     for (int i=1;i<=n;i++) 82         u[i]=i,h[i]=1; 83 }  84  85 void solve() 86 { 87     scanf("%d%d",&n,&m); 88     tim=0; 89     init(); 90     for (int i=0;i<m;i++) 91     { 92         int op,a,b; 93         scanf("%d%d%d",&op,&a,&b); 94         a^=preans; 95         b^=preans; 96         if (!op) union_set(a,b); 97             else mintime(a,b); 98     } 99 } 100 101 int main()102 {103     solve();104     return 0;105 }

 

【并查集】BZOJ4668-冷战