zoukankan      html  css  js  c++  java
  • 【SHOI2008】cactus仙人掌图

    题面

    http://darkbzoj.tk/problem/1023

    1. 仙人掌上建有根圆方树(对于方点维护$son[x][i]$和$len[x][i]$,改变$len[x][i]$的定义以规避讨论)
    2. 单调队列维护加入元素和查找最大值的操作。
    3. 其他思路大体上和最短路(http://darkbzoj.tk/problem/2125)一样。
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<stack>
    #include<vector>
    #define ri register int
    #define N 100500
    using namespace std;
    
    int n,tn,m;
    int cir[N];
    int a[N];
    int ans;
    
    inline int read() {
      int ret=0,f=0; char ch=getchar();
      while (ch<'0' || ch>'9') f|=(ch=='-'),ch=getchar();
      while (ch>='0'&&ch<='9') ret*=10,ret+=ch-'0',ch=getchar();
      return f?-ret:ret;
    }
    
    struct tree {
      vector<int> son[N],len[N];
      int f[N];
      void add_edge(int a,int b,int c) {
        son[b].push_back(a);
        len[b].push_back(c);
      }
      void dp(int x) {
        if (!son[x].size()) {
          f[x]=0;
          return;
        }
        for (ri i=0;i<son[x].size();i++) dp(son[x][i]);
        if (x<=tn) {
          f[x]=-1;
          int p=-1;
          for (ri i=0;i<son[x].size();i++) if (f[son[x][i]]>f[x]) f[x]=f[son[x][i]],p=son[x][i];
          if (f[x]>ans) ans=f[x];
          for (ri i=0;i<son[x].size();i++) if (son[x][i]!=p) if (f[x]+f[son[x][i]]>ans) ans=f[x]+f[son[x][i]];
        }
        else {
          f[x]=0;
          int l=son[x].size();
          for (ri i=0;i<l;i++) {
            if (min(cir[x]-len[x][i],len[x][i])+f[son[x][i]]>f[x]) f[x]=min(cir[x]-len[x][i],len[x][i])+f[son[x][i]];
            son[x].push_back(son[x][i]);
            len[x].push_back(cir[x]+len[x][i]);
          }
          deque<int> q;
          while (!q.empty()) q.pop_back();
          for (ri i=0;i<son[x].size();i++) {
            int a=son[x][i],dis=len[x][i];
            while (q.size() && 2*(dis-len[x][q.back()])>cir[x]) q.pop_back();
            if (q.size() && f[a]+f[son[x][q.back()]]+dis-len[x][q.back()]>ans) ans=f[a]+f[son[x][q.back()]]+dis-len[x][q.back()];
            while (q.size() && f[a]-dis>f[son[x][q.front()]]-len[x][q.front()]) q.pop_front();
            q.push_front(i);
          }
        }
      }
    } T;
    
    struct graph {
      vector<int> to[N];
      int dfn[N],low[N],cnt;
      int pre[N],dr[N];
      stack<int> s;
      void add_edge(int a,int b) {
        to[a].push_back(b);
        to[b].push_back(a);
      }
      void tarjan(int x) {
        dfn[x]=low[x]=++cnt; s.push(x);
        for (ri i=0;i<to[x].size();i++) {
          int y=to[x][i];
          if (dfn[y]) low[x]=min(low[x],dfn[y]);
          else {
            pre[y]=x; dr[y]=dr[x]+1; tarjan(y);
            if (low[y]>=dfn[x]) {
              ++n;
              cir[n]=dr[s.top()]-dr[x]+1;
              T.add_edge(n,x,0);
              int t;
              do {
                t=s.top(); s.pop();
                T.add_edge(t,n,cir[n]-dr[t]+dr[x]);
              }
              while (t!=y);
            }
            low[x]=min(low[x],low[y]);
          }
        }
      }
    } G;
    
    int main() {
      tn=n=read(); m=read();
      for (ri i=1;i<=m;i++) {
        int k=read();
        for (ri j=1;j<=k;j++) a[j]=read();
        for (ri j=2;j<=k;j++) G.add_edge(a[j-1],a[j]);
      }
      G.cnt=0;
      G.tarjan(1);
      T.dp(1);
      printf("%d
    ",ans);
    }
  • 相关阅读:
    Java实现 LeetCode 69 x的平方根
    Java实现 LeetCode 68 文本左右对齐
    Java实现 LeetCode 68 文本左右对齐
    Java实现 LeetCode 68 文本左右对齐
    Java实现 LeetCode 67 二进制求和
    Java实现 LeetCode 67 二进制求和
    Java实现 LeetCode 67 二进制求和
    Java实现 LeetCode 66 加一
    Java实现 LeetCode 66 加一
    CxSkinButton按钮皮肤类
  • 原文地址:https://www.cnblogs.com/shxnb666/p/11076498.html
Copyright © 2011-2022 走看看