zoukankan      html  css  js  c++  java
  • 【并查集】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
    ",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 }
  • 相关阅读:
    封装tip控件
    Javascirpt中创建对象的几种方式
    使用Servlet上传文件
    Struts2 基本配置
    使用JQuery实现手风琴布局
    winform下自绘提示框风格窗体
    环形进度条
    Oracle中获取当前时间半小时前的时间
    JSTL+MyEclipse8.5+Tomcat配置
    使用CSS和jQuery实现对话框
  • 原文地址:https://www.cnblogs.com/iiyiyi/p/5876139.html
Copyright © 2011-2022 走看看