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

  • 相关阅读:
    A Simple Problem with Integers poj 3468 多树状数组解决区间修改问题。
    Fliptile 开关问题 poj 3279
    Face The Right Way 一道不错的尺取法和标记法题目。 poj 3276
    Aggressive cows 二分不仅仅是查找
    Cable master(二分题 注意精度)
    B. Pasha and String
    Intervals poj 1201 差分约束系统
    UITextField的快速基本使用代码块
    将UIImage转换成圆形图片image
    color转成image对象
  • 原文地址:https://www.cnblogs.com/Konjakmoyu/p/6403567.html
Copyright © 2011-2022 走看看