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);
    }
  • 相关阅读:
    SQL语言的组成
    存储过程中使用事务
    sql语法:inner join on, left join on, right join on详细使用方法
    Sql Server服务 远程过程调用失败
    UML学习之初步总结
    UML学习之用例图
    使用redis
    msserver的update or insert语句
    c#操作注册表的意外
    托管代码编写mssql存储过程
  • 原文地址:https://www.cnblogs.com/shxnb666/p/11076498.html
Copyright © 2011-2022 走看看