【并查集】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 }

 

posted @ 2016-09-16 11:34  iiyiyi  阅读(267)  评论(0编辑  收藏  举报