• bzoj1023


    研究了一下仙人掌
    首先,仙人掌虽然不是树,但却有很强的树的既视感
    如果把每个环都看做一个点,那么他就是一棵树
    当然这不能直接缩环,因为环和环可以有一个交点
    如果是树,求直径都会做,令f[i]表示i到子树的最长距离然后弄一弄
    但现在是树套环,怎么弄?
    我们先根据dfs时间戳的思想,dfs下去,构成了一棵dfs树
    我们的思想是先处理桥(树边),再处理环
    这时候f[i]表示i在dfs树上i到子树的最长距离
    dfs到i时,我们先用树形dp的思想求出不考虑环的f[i]
    然后再把环拉出来一个个考虑,显然环上点j的f[j]除了和环上另一个点组成的路径对ans直接影响外
    只会通过对最高点(时间戳最小的点)i的f[i]的影响来影响其他非以i为根的子树上的点
    所以我们用环上的点来更新f[i]即可
    再考虑环上两点路径对ans直接影响,枚举点j,显然可以得到
    显然可以得到ans=max(ans,f[j]+max(f[k]+dis(j,k)));
    我们对环上的点按照dfs树上的深度由小到大编号,t是环上点总数
    可以得到dis(j,k)=min(k-j,t-k+j-i+1) (k>j)
    考虑到环上两点间距离有两种情况,对此我们可以把环复制一遍然后做单调队列即可
    最后,显然所有更新都是先更新ans再更新f[i],

      1 {$m 1000000}
      2 type node=record
      3        po,next:longint;
      4      end;
      5 
      6 var a,q:array[0..100010] of longint;
      7     fa,low,dfn,f,p,d:array[0..50010] of longint;
      8     e:array[0..2000010] of node;
      9     j,s,ans,h,len,i,n,m,x,y:longint;
     10 
     11 function min(a,b:longint):longint;
     12   begin
     13     if a>b then exit(b) else exit(a);
     14   end;
     15 
     16 function max(a,b:longint):longint;
     17   begin
     18     if a>b then exit(a) else exit(b);
     19   end;
     20 
     21 procedure add(x,y:longint);
     22   begin
     23     inc(len);
     24     e[len].po:=y;
     25     e[len].next:=p[x];
     26     p[x]:=len;
     27   end;
     28 
     29 procedure dp(x,y:longint);
     30   var t,h,r,i,p:longint;
     31   begin
     32     t:=d[y]-d[x]+1;  //环上点的数目
     33     h:=1;
     34     r:=1;
     35     p:=y;
     36     for i:=t downto 1 do
     37     begin
     38       a[i]:=f[p];
     39       a[i+t]:=a[i];  //复制一遍,把两点间距离转化为编号差
     40       p:=fa[p];
     41     end;
     42     q[1]:=1; //维护单调减的双端队列
     43     for i:=2 to t+t div 2 do
     44     begin
     45       while (h<=r) and (q[h]<i-t div 2) do inc(h); //队头的点和当前点的距离已经不是最短距离
     46       ans:=max(ans,a[q[h]]+a[i]+i-q[h]);
     47       while (h<=r) and (a[q[r]]-q[r]<=a[i]-i) do dec(r);
     48       inc(r);
     49       q[r]:=i;
     50     end;
     51     for i:=2 to t do
     52       f[x]:=max(f[x],a[i]+min(i-1,t-i+1));
     53   end;
     54 
     55 procedure tarjan(x:longint);
     56   var i,y:longint;
     57   begin
     58     inc(h);
     59     dfn[x]:=h;
     60     low[x]:=h;
     61     i:=p[x];
     62     while i<>0 do
     63     begin
     64       y:=e[i].po;
     65       if fa[x]<>y then
     66       begin
     67         if dfn[y]=0 then
     68         begin
     69           fa[y]:=x;
     70           d[y]:=d[x]+1;
     71           tarjan(y);
     72         end;
     73         low[x]:=min(low[x],low[y]);
     74         if dfn[x]<low[y] then  //如果与x和x的祖先不构成环
     75         begin
     76           ans:=max(ans,f[x]+f[y]+1);
     77           f[x]:=max(f[x],f[y]+1);
     78         end;
     79       end;
     80       i:=e[i].next;
     81     end;
     82     i:=p[x];
     83     while i<>0 do
     84     begin
     85       y:=e[i].po;
     86       if (fa[y]<>x) and (dfn[x]<dfn[y]) then //与x节点成环
     87         dp(x,y);
     88       i:=e[i].next;
     89     end;
     90   end;
     91 
     92 begin
     93   readln(n,m);
     94   for i:=1 to m do
     95   begin
     96     read(s);
     97     read(x);
     98     for j:=2 to s do
     99     begin
    100       read(y);
    101       add(x,y);
    102       add(y,x);
    103       x:=y;
    104     end;
    105   end;
    106   tarjan(1);
    107   writeln(ans);
    108 end.
    View Code
  • 相关阅读:
    【SQL Server学习笔记】Service Broker创建异步的、数据驱动的消息应用程序
    记录几句不错的话
    DBA最缺的不是技术
    小数点引起的数据类型转换问题
    hdu 3062 2SAT最基础题
    POJ 1679 判断最小生成树是否唯一
    POJ 1459 构图+最大流(Edmond_karp模版)
    POJ 3522 最大边与最小边差值最小的生成树
    POJ 1659 根据度序列构图
    POJ 1273 求最大流(Edmond_karp模板题)
  • 原文地址:https://www.cnblogs.com/phile/p/4473006.html
Copyright © 2020-2023  润新知