• bzoj 1791: [Ioi2008]Island 岛屿


      1 #include<iostream>
      2 #include<cstdio>
      3 #define M 1000009
      4 using namespace std;
      5 int q[2*M],cnt,n,head[M],next[2*M],u[2*M],l[2*M],du[M],c[M],t,v[M];
      6 long long f[M],d[M],d1[2*M],a[2*M],ans;
      7 void jia(int a1,int a2,int a3)
      8 {
      9     cnt++;
     10     next[cnt]=head[a1];
     11     head[a1]=cnt;
     12     u[cnt]=a2;
     13     l[cnt]=a3;
     14     du[a1]++;
     15     return;
     16 }
     17 void dfs(int k,int x)
     18 {
     19     c[x]=k;
     20     for(int i=head[x];i;i=next[i])
     21       if(!c[u[i]])
     22         dfs(k,u[i]);
     23     return;
     24 }
     25 void tuopu()
     26 {
     27     int h=0,t=0;
     28     for(int i=1;i<=n;i++)
     29       if(du[i]==1)
     30         {
     31             t++;
     32             q[t]=i;
     33         }
     34     for(;h<t;)
     35       {
     36         h++;
     37         int p=q[h];
     38         for(int i=head[p];i;i=next[i])
     39           if(du[u[i]]!=1)
     40             {
     41                 du[u[i]]--;
     42                 d[c[p]]=max(d[c[p]],f[p]+f[u[i]]+l[i]);
     43                 f[u[i]]=max(f[u[i]],f[p]+l[i]);
     44                 if(du[u[i]]==1)
     45                   {
     46                     t++;
     47                     q[t]=u[i];
     48                   }
     49             }
     50       }
     51 }
     52 void dp(int t1,int x)
     53 {
     54     int m=0,y=x,i;
     55     do
     56       {
     57         a[++m]=f[y];
     58         du[y]=1;
     59         for(i=head[y];i;i=next[i])
     60           if(du[u[i]]>1)
     61             {
     62                 d1[m+1]=d1[m]+l[i];
     63                 y=u[i];
     64                 break;
     65             }
     66       }while(i);
     67     if(m==2)
     68       {
     69         int qq=0;
     70         for(int i=head[y];i;i=next[i])
     71           if(u[i]==x)
     72             qq=max(qq,l[i]);
     73         d[c[x]]=max(d[c[x]],a[1]+a[2]+qq);
     74         return;
     75       }
     76     for(int i=head[y];i;i=next[i])
     77       if(u[i]==x)
     78         {
     79             d1[m+1]=d1[m]+l[i];
     80             break;
     81         }
     82     for(int i=1;i<=m;i++)
     83       {
     84         a[m+i]=a[i];
     85         d1[m+i]=d1[m+1]+d1[i];
     86       }
     87     int h=t=1;
     88     q[1]=1;
     89     for(int i=2;i<=2*m;i++)
     90       {
     91         for(;h<=t&&i-q[h]>=m;h++);
     92         d[t1]=max(d[t1],a[q[h]]+a[i]+d1[i]-d1[q[h]]);
     93         for(;h<=t&&a[q[t]]-d1[q[t]]<=a[i]-d1[i];t--);
     94         t++;
     95         q[t]=i;
     96       }
     97 }
     98 int main()
     99 {
    100     scanf("%d",&n);
    101     for(int i=1;i<=n;i++)
    102       {
    103         int a1,a2;
    104         scanf("%d%d",&a1,&a2);
    105         jia(i,a1,a2);
    106         jia(a1,i,a2);
    107       }
    108     for(int i=1;i<=n;i++)
    109       if(!c[i])
    110         {
    111           t++;
    112           dfs(t,i);
    113         }
    114     tuopu();
    115     for(int i=1;i<=n;i++)
    116       if(du[i]>1&&!v[c[i]])
    117         {
    118             v[c[i]]=1;
    119             dp(c[i],i);
    120             ans+=d[c[i]];
    121         }
    122     printf("%lld
    ",ans);
    123     return 0;
    124 }

    这个题建出图来之后,是一个基环树森林,先把非环部分的最长链用DP求出来,在把环拆开,变为两倍,找环上两点之间的距离加上在这两个点的子树中,以这两个点为端点的最长链的

    长度,注意如果是两个点的环,需要特判,因为不一定能找到那条最长的边。

  • 相关阅读:
    sql语句中的通配符
    Q&A 20090922
    Web大文件上传
    作别2010, 迎来2011的第一个工作日
    .Net 中 获取当前应用程序启动目录的几个方法
    asp.net身份验证和使用Silverlight的问题
    常用正则表达式
    最完美的xslt数值函数与字符串函数
    SQL2005的分页存储过程,支持多表多关联,亲测高效绝对可用
    处理大并发下的dropdownlist数据关联
  • 原文地址:https://www.cnblogs.com/xydddd/p/5277517.html
Copyright © 2020-2023  润新知