zoukankan      html  css  js  c++  java
  • 【BZOJ 2791】 2791: [Poi2012]Rendezvous (环套树、树链剖分LCA)

    2791: [Poi2012]Rendezvous

    Description


    给定一个n个顶点的有向图,每个顶点有且仅有一条出边。
    对于顶点i,记它的出边为(i, a[i])。
    再给出q组询问,每组询问由两个顶点a、b组成,要求输出满足下面条件的x、y:
    1. 从顶点a沿着出边走x步和从顶点b沿着出边走y步后到达的顶点相同。
    2. 在满足条件1的情况下max(x,y)最小。
    3. 在满足条件1和2的情况下min(x,y)最小。
    4. 在满足条件1、2和3的情况下x>=y。
    如果不存在满足条件1的x、y,输出-1 -1。

    Input

    第一行两个正整数n和q (n,q<=500,000)。
    第二行n个正整数a[1],a[2],...,a[n] (a[i]<=n)。
    下面q行,每行两个正整数a,b (a,b<=n),表示一组询问。

    Output

    输出q行,每行两个整数。

    Sample Input

    12 5
    4 3 5 5 1 1 12 12 9 9 7 1
    7 2
    8 11
    1 2
    9 10
    10 5

    Sample Output

    2 3
    1 2
    2 2
    0 1
    -1 -1

    HINT

    Source

    【分析】

      一开始以为是无向边ORZ。。

      其实有向边只要改一点点东西。

      那个x>=y是用来省掉SPJ的,不是题目要求

      无向边的话,首先是一个基环森林,很明显是求最短路径然后除以二。

      有向边的话,很多路径是固定的,

      首先不是一个联通块的一定无法到达,是一个联通块的一定能到达(也许你觉得有向边不一定可以,但事实上是可以的,因为每个点只有一条出边的特殊性质)

      这种特殊性质告诉我们:

      环一定是通的,就是从环上任意一点走环一定能走回自己。

      基环树下面的点的连边一定是向上的(考虑一个点只有一条出边,而环上的根的出边已经贡献给环了)

      所以如果是同一棵树,那么求LCA,答案是唯一的。

      如果不是,那么环上面也只有两种走法,两个答案比较一下即可。

      【其实一开始看错题之后觉得边有向很难搞,其实知道性质就很简单了】

      1 #include<cstdio>
      2 #include<cstdlib>
      3 #include<cstring>
      4 #include<iostream>
      5 #include<algorithm>
      6 using namespace std;
      7 #define Maxn 500010
      8 
      9 int mymax(int x,int y) {return x>y?x:y;}
     10 int mymin(int x,int y) {return x<y?x:y;}
     11 int myabs(int x) {return x>0?x:-x;}
     12 
     13 struct node
     14 {
     15     int x,y,next,o;
     16     bool p;
     17 }t[Maxn*2];int len=0;
     18 int first[Maxn];
     19 
     20 void ins(int x,int y)
     21 {
     22     t[++len].x=x;t[len].y=y;
     23     t[len].next=first[x];first[x]=len;
     24     t[len].p=1;
     25     if(len%2==0) t[len].o=len-1;
     26     else t[len].o=len+1;
     27 }
     28 
     29 int fa[Maxn],r1[Maxn],r2[Maxn];
     30 int ffa(int x)
     31 {
     32     if(x!=fa[x]) fa[x]=ffa(fa[x]);
     33     return fa[x];
     34 }
     35 
     36 int dis[Maxn];
     37 bool onc[Maxn];
     38 int dfs0(int x,int ff,int rr)
     39 {
     40     dis[x]=dis[ff]+1;
     41     if(x==rr) {onc[x]=1;return 1;}
     42     for(int i=first[x];i;i=t[i].next) if(t[i].y!=ff)
     43     {
     44         int y=t[i].y,z=dfs0(y,x,rr);
     45         if(z!=0) {t[i].p=t[t[i].o].p=0;onc[x]=1;return z+1;}
     46     }
     47     return 0;
     48 }
     49 
     50 int tp[Maxn],son[Maxn],sm[Maxn];
     51 int dep[Maxn],siz[Maxn],fd[Maxn];
     52 void dfs1(int x,int ff)
     53 {
     54     sm[x]=1;son[x]=0;fd[x]=ff;
     55     for(int i=first[x];i;i=t[i].next) if(t[i].p&&t[i].y!=ff)
     56     {
     57         int y=t[i].y;
     58         dis[y]=dis[x];
     59         dep[y]=dep[x]+1;
     60         dfs1(y,x);
     61         sm[x]+=sm[y];
     62         if(son[x]==0||sm[son[x]]<sm[y]) son[x]=y;
     63     }
     64 }
     65 
     66 void dfs2(int x,int ff,int tpp)
     67 {
     68     tp[x]=tpp;
     69     if(son[x]) dfs2(son[x],x,tpp);
     70     for(int i=first[x];i;i=t[i].next) if(t[i].y!=ff&&t[i].y!=son[x]&&t[i].p)
     71     {
     72         dfs2(t[i].y,x,t[i].y);
     73     }
     74 }
     75 
     76 void ffind(int x,int y)
     77 {
     78     int xx=x,yy=y;
     79     while(tp[x]!=tp[y])
     80     {
     81         if(dep[tp[x]]<dep[tp[y]]) swap(x,y);
     82         x=fd[tp[x]];
     83     }
     84     if(dep[x]>dep[y]) swap(x,y);
     85     // return dep[xx]+dep[yy]-2*dep[x];
     86     printf("%d %d
    ",dep[xx]-dep[x],dep[yy]-dep[x]);
     87 }
     88 
     89 int main()
     90 {
     91     int n,q;
     92     scanf("%d%d",&n,&q);
     93     memset(first,0,sizeof(first));
     94     memset(r1,0,sizeof(r1));
     95     memset(onc,0,sizeof(onc));
     96     for(int i=1;i<=n;i++) fa[i]=i;
     97     for(int i=1;i<=n;i++)
     98     {
     99         int x;
    100         scanf("%d",&x);
    101         if(ffa(x)==ffa(i))
    102         {
    103             r1[ffa(x)]=x;r2[ffa(x)]=i;
    104         }
    105         else
    106         {
    107             if(r1[ffa(x)]!=0) r1[ffa(i)]=r1[ffa(x)],r2[ffa(i)]=r2[ffa(x)];
    108             fa[ffa(x)]=ffa(i);
    109             ins(x,i);ins(i,x);
    110         }
    111     }
    112     for(int i=1;i<=n;i++) if(ffa(i)==i)
    113     {
    114         dis[r1[i]]=0;
    115         siz[i]=dfs0(r1[i],0,r2[i]);
    116     }
    117     for(int i=1;i<=n;i++) if(onc[i])
    118     {
    119         dep[i]=0;
    120         dfs1(i,0);
    121         dfs2(i,0,i);
    122     }
    123     for(int i=1;i<=q;i++)
    124     {
    125         int x,y;
    126         scanf("%d%d",&x,&y);
    127         if(ffa(x)!=ffa(y)) {printf("-1 -1
    ");continue;}
    128         int sum;
    129         if(dis[x]!=dis[y])
    130         {
    131             sum=mymin(siz[ffa(x)]-myabs(dis[x]-dis[y]),myabs(dis[x]-dis[y]));
    132             int x1,y1,x2,y2;
    133             if(dis[x]<dis[y])
    134             {
    135                 x1=dep[x]+dis[y]-dis[x];y1=dep[y];
    136                 x2=dep[x];y2=dep[y]+siz[ffa(x)]-(dis[y]-dis[x]);
    137             }
    138             else
    139             {
    140                 x1=dep[x];y1=dep[y]+dis[x]-dis[y];
    141                 x2=dep[x]+siz[ffa(x)]-(dis[x]-dis[y]);y2=dep[y];
    142             }
    143             if(mymax(x1,y1)<mymax(x2,y2)) printf("%d %d
    ",x1,y1);
    144             else if(mymax(x1,y1)>mymax(x2,y2)) printf("%d %d
    ",x2,y2);
    145             else
    146             {
    147                 if(mymin(x1,y1)<mymin(x2,y2)) printf("%d %d
    ",x1,y1);
    148                 else if(mymin(x1,y1)>mymin(x2,y2)) printf("%d %d
    ",x2,y2);
    149                 else if(x1>=y1) printf("%d %d
    ",x1,y1);
    150                 else printf("%d %d
    ",x2,y2);
    151             }
    152         }
    153         else ffind(x,y);
    154     }
    155     return 0;
    156 }
    View Code

    2017-02-15 22:07:35

  • 相关阅读:
    Rebots协议是什么?
    Requests库入门
    jieba库的使用及实例
    第六周 python组合数据类型
    python 有基础入门程序
    字符与字符串操作归纳[持续更新]
    C++调用bat并实现传值
    Python如何运行程序
    Execl数据上传到数据库
    xml 文件操作
  • 原文地址:https://www.cnblogs.com/Konjakmoyu/p/6403567.html
Copyright © 2011-2022 走看看