• bzoj1023: [SHOI2008]cactus仙人掌图


    题解可以看这篇,写的很清楚……
    http://z55250825.blog.163.com/blog/static/150230809201412793151890/

    然后我的单调队列写出来竟然和他不一样……
    max(f[i]+f[j]+j-i)j属于[i+1,i+sum/2]的话,对于j的话,不就是max(f[i]-i)+f[j]+j,维护f[i]-i递增不就行了么?

    那么说一下这种环套树的基本写法……

    首先是建图
    然后跑tarjan,跑得时候要记录下某个点的父亲,然后如果某个点x的某个儿子son存在dfn[x]<low[too],那么明显x-son就是一个桥……这一部分可以看成是树dp中某个节点和儿子。然后某个点跑完tarjan后再找出它所有fa[son]<>x且dfn[x]<dfn[too],这时就是以x到too再到x的环,这时候就跑个循环dp,只不过要注意那个x取too就不能取,too取x就不能取,两遍for解决……

    也就是树当树,环当环处理啦……

    type
      arr=record
        toward,next:longint;
      end;
     
    const
      maxm=3000000;
      maxn=300000;
     
    var
      edge:array[0..maxm]of arr;
      first,num,a,f,p,dfn,low,dep,fa:array[0..maxn]of longint;
      n,m,time,tot,ans:longint;
     
     
    function max(x,y:longint):longint;
    begin
      if x<y then exit(y);
      exit(x);
    end;
     
    function min(x,y:longint):longint;
    begin
      if x<y then exit(x);
      exit(y);
    end;
     
    procedure addedge(i,j:longint);
    begin
      inc(tot);
      edge[tot].toward:=j;
      edge[tot].next:=first[i];
      first[i]:=tot;
    end;
     
    procedure dp(x,root:longint);
    var
      sum,head,tail,i:longint;
    begin
      sum:=dep[x]-dep[root]+1;
      i:=x;
      while sum>0 do begin
        num[sum]:=f[x];
        x:=fa[x];
        dec(sum);
      end;
      x:=i;
      sum:=dep[x]-dep[root]+1;
      for i:=1 to sum do
        num[i+sum]:=num[i];
      head:=1;
      tail:=1;
      p[1]:=1;
      for i:=2 to sum<<1 do begin
        while (head<=tail) and (p[head]+sum>>1<i) do inc(head);
        ans:=max(ans,num[p[head]]-p[head]+num[i]+i);
        while (head<=tail) and (num[p[tail]]-p[tail]<num[i]-i) do dec(tail);
        inc(tail);
        p[tail]:=i;
      end;
      for i:=2 to sum do
        f[root]:=max(f[root],min(i-1,sum-i+1)+num[i]);
    end;
     
    procedure tarjan(x:longint);
    var
      i,too:longint;
    begin
      inc(time);
      dfn[x]:=time;
      low[x]:=time;
      i:=first[x];
      while i>0 do begin
        too:=edge[i].toward;
        if too<>fa[x] then begin
          if dfn[too]=0 then begin
            dep[too]:=dep[x]+1;
            fa[too]:=x;
            tarjan(too);
            if low[too]<low[x] then low[x]:=low[too];
          end
          else
            if dfn[too]<low[x] then low[x]:=dfn[too];
          if dfn[x]<low[too] then begin
            ans:=max(ans,f[x]+f[too]+1);
            f[x]:=max(f[x],f[too]+1);
          end;
        end;
        i:=edge[i].next;
      end;
      i:=first[x];
      while i>0 do begin
        too:=edge[i].toward;
        if (fa[too]<>x)  and (dfn[x]<dfn[too]) then dp(too,x);
        i:=edge[i].next;
      end;
    end;
     
    procedure into;
    var
      i,j,k:longint;
    begin
      readln(n,m);
      for i:=1 to m do begin
        read(k,a[1]);
        for j:=2 to k do begin
          read(a[j]);
          addedge(a[j],a[j-1]);
          addedge(a[j-1],a[j]);
        end;
      end;
    end;
     
    procedure work;
    begin
      time:=0;
      ans:=0;
      dep[1]:=1;
      tarjan(1);
      writeln(ans);
    end;
     
    begin
      into;
      work;
    end.
    View Code

     (有时间再搞搞丧心病狂的动态仙人掌)

    因疲惫而轻易入眠,是对自己一天努力的最好褒奖。 要和泪子一起努力怀抱梦想对抗残酷的现实……
  • 相关阅读:
    Execution Contexts (执行上下文)
    OOP—ECMAScript实现详解
    requireJS入门
    SqlServer 傲娇的表变量
    CSharp进阶 引用类型引发的血案
    CSharp进阶 都是请求惹的祸
    z-index问题
    js中事件(自定义事件)
    做了个后末日朋克风的梦
    昨晚的梦
  • 原文地址:https://www.cnblogs.com/Macaulish/p/4180772.html
Copyright © 2020-2023  润新知