zoukankan      html  css  js  c++  java
  • 1023: [SHOI2008]cactus仙人掌图(DP+单调队列优化)

    这道题吗= =首先解决了我多年以来对仙人掌图的疑问,原来这种高大上的东西原来是这个啊= =

    然后,看到这种题,首先必须的就是缩点= =

    缩点完之后呢,变成在树上找最长路了= =直接树形dp了

    那么那些环呢,就是一个环形dp了,可以先把它拆成一条链,然后注意到最长路径=max(f[i]+f[j]-dist(i,j))  拆成链的话dist(i,j)=i-j 然后就发现dist(i,j)有单调性,就可以用单调队列优化了= =

    这样写就可以a了= =

    ps1:今天发现有人给我留言了真开心QAQ 感觉自己写了这么久还是有人看到的QAQ 继续加油吧!!!

    ps2:bzoj的808端口坏了现在上都得改网址真麻烦QAQ

    ps3:刷了好久感觉没啥精神了这个月感觉刷不了多少了QAQ 所以众多STOI补番队的成员啊,这个月的占领头版计划就交给你们了QAQ

    CODE:

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<iostream>
    using namespace std;
    #define maxn 50100
    #define maxm 20000100
    struct edges{
     int to,next;
    }edge[maxm];
    int l,next[maxn];
    int addedge(int x,int y){
     edge[++l]=(edges){y,next[x]};next[x]=l;
     edge[++l]=(edges){x,next[y]};next[y]=l;
     return 0;
    }
    int f[maxn],q[maxn*2],ans,que[maxn],pre[maxn],dep[maxn];
    int dp(int y,int x ){
     int l=dep[y]-dep[x]+1;
     int t=y;
     while (l) {
      q[l--]=f[t];
      t=pre[t];
     }
     l=dep[y]-dep[x]+1;
     for (int i=1;i<=l;i++) q[i+l]=q[i];
     int h=0;
     t=1;
     for (int i=2;i<=(l>>1)+1;i++) {
      while (h>=t&&que[h]+q[que[h]]<=i+q[i]) h--;
      que[++h]=i;
     }
     int j=(l>>1)+1;
     for (int i=1;i<=(l<<1)-(l>>1);i++){
      while (h>=t&&que[t]<=i) t++;
      ans=max(ans,que[t]+q[que[t]]+q[i]-i);
      j++;
      while (h>=t&&que[h]+q[que[h]]<=j+q[j]) h--;
      que[++h]=j;
     }
     for (int i=2;i<=l;i++) f[x]=max(f[x],min(i-1,l-i+1)+q[i]);
     return 0;
    }
    int low[maxn],dfn[maxn],clo;
    int dfs(int u,int fa){
     pre[u]=fa;
     dep[u]=dep[fa]+1;
     low[u]=dfn[u]=++clo;
     for (int i=next[u];i;i=edge[i].next)
      if (edge[i].to!=fa) {
       if (!low[edge[i].to]){
        dfs(edge[i].to,u);
        low[u]=min(low[u],low[edge[i].to]);
       }else low[u]=min(low[u],dfn[edge[i].to]);
       if (dfn[u]<low[edge[i].to]) {
        ans=max(ans,f[u]+f[edge[i].to]+1);
        f[u]=max(f[u],f[edge[i].to]+1);
       }
      }
     for (int i=next[u];i;i=edge[i].next)
      if (pre[edge[i].to]!=u&&dfn[u]<dfn[edge[i].to]) dp(edge[i].to,u);
     return 0;
    }
    int main(){
     int n,m;
     scanf("%d%d",&n,&m);
     for (int i=1;i<=m;i++) {
      int k,x,y;
      scanf("%d",&k);
      scanf("%d",&x);
      for (int j=2;j<=k;j++) {
       scanf("%d",&y);
       addedge(x,y);
       swap(x,y);
      }
     }
     dfs(1,0);
     printf("%d ",ans); 
     return 0;
    }

  • 相关阅读:
    函数节流和防抖
    前端优化
    webpack模块
    link和@import的区别
    BFC--CSS
    javaoop_破解jdbc
    javaoop反射
    java-oop集合与泛型
    java中几个小遗漏
    java异常处理和日志管理
  • 原文地址:https://www.cnblogs.com/New-Godess/p/4348935.html
Copyright © 2011-2022 走看看