并查集BZOJ4668-冷战
Posted Yiyi
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了并查集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-冷战的主要内容,如果未能解决你的问题,请参考以下文章