• LG P4381 [IOI2008]Island


    Description

    你准备浏览一个公园,该公园由 $N$ 个岛屿组成,当地管理部门从每个岛屿 $i$ 出发向另外一个岛屿建了一座长度为$L_i$ 的桥,不过桥是可以双向行走的。同时,每对岛屿之间都有一艘专用的往来两岛之间的渡船。相对于乘船而言,你更喜欢步行。你希望经过的桥的总长度尽可能长,但受到以下的限制:

      • 可以自行挑选一个岛开始游览。
      • 任何一个岛都不能游览一次以上。
      • 无论任何时间,你都可以由当前所在的岛 $S$

     去另一个从未到过的岛 $D$。从 $S$ 到 $D$ 有如下方法:

      • 步行:仅当两个岛之间有一座桥时才有可能。对于这种情况,桥的长度会累加到你步行的总距离中。
      • 渡船:你可以选择这种方法,仅当没有任何桥和以前使用过的渡船的组合可以由 $S$ 走到 $D$ (当检查是否可到达时,你应该考虑所有的路径,包括经过你曾游览过的那些岛)。

    注意,你不必游览所有的岛,也可能无法走完所有的桥。

    请你编写一个程序,给定 $N$ 座桥以及它们的长度,按照上述的规则,计算你可以走过的桥的长度之和的最大值。

    Solution

    求基环森林中每个基环树的直径之和

    有两种情况

    • 直径在某个树上(不跨越环)
    • 直径跨越环

    对于第一种情况,树形DP

    对于第二种情况,优先队列优化DP

    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<deque>
    #include<cmath>
    using namespace std;
    long long n,tot,head[1000005],vst[1000005],r[1000005],cnt,st;
    long long sum[2000005],maxx,dp[2000005],ans,f[2000005];
    bool vis[1000005];
    struct Edge
    {
        long long to,nxt;
        long long w;
    }edge[2000005];
    inline long long read()
    {
        long long w=0,f=1;
        char ch=0;
        while(ch<'0'||ch>'9')
        {
            if(ch=='-')
                f=-1;
            ch=getchar();
        }
        while(ch>='0'&&ch<='9')
        {
            w=(w<<1)+(w<<3)+ch-'0';
            ch=getchar();
        }
        return w*f;
    }
    bool dfs1(long long k,long long e)
    {
        if(vst[k]==1)
        {
            vst[k]=2;
            r[++cnt]=k;
            vis[k]=true;
            return true;
        }
        vst[k]=1;
        for(long long i=head[k];i;i=edge[i].nxt)
        {
            if(i!=((e-1)^1)+1&&dfs1(edge[i].to,i))
            {
                if(vst[k]==1)
                {
                    r[++cnt]=k;
                    sum[cnt]=sum[cnt-1]+edge[i].w;
                    vis[k]=true;
                    return true;
                }
                sum[st-1]=sum[st]-edge[i].w;
                return false;
            }
        }
        return false;
    }
    void dfs2(long long k,long long f)
    {
        vis[k]=true;
        for(long long i=head[k];i;i=edge[i].nxt)
        {
            long long v=edge[i].to;
            if(!vis[v])
            {
                dfs2(v,k);
                maxx=max(maxx,dp[k]+dp[v]+edge[i].w);
                dp[k]=max(dp[k],dp[v]+edge[i].w);
            }
        }
    }
    int main()
    {
        n=read();
        for(long long i=1;i<=n;i++)
        {
            long long x=read(),y=read();
            edge[++tot]=(Edge){x,head[i],y};
            head[i]=tot;
            edge[++tot]=(Edge){i,head[x],y};
            head[x]=tot;
        }
        for(long long i=1;i<=n;i++)
        {
            if(!vis[i])
            {
                st=cnt+1;
                maxx=-1;
                dfs1(i,0);
                for(long long j=st;j<=cnt;j++)
                {
                    dfs2(r[j],0);
                }
                for(long long j=st;j<=cnt;j++)
                {
                    sum[j+cnt-st+1]=sum[j+cnt-st]+sum[j]-sum[j-1];
                    f[j]=f[j+cnt-st+1]=dp[r[j]];
                }
                deque<long long>q;
                for(long long j=st;j<=2*cnt-st+1;j++)
                {
                    while(q.size()&&q.front()<=j-cnt+st-1)
                    {
                        q.pop_front();
                    }
                    if(q.size())
                    {
                        maxx=max(maxx,f[j]+sum[j]+f[q.front()]-sum[q.front()]);
                    }
                    while(q.size()&&f[j]-sum[j]>=f[q.back()]-sum[q.back()])
                    {
                        q.pop_back();
                    }
                    q.push_back(j);
                }
                ans+=maxx;
            }
        }
        printf("%lld
    ",ans);
        return 0;
    }
    Island
  • 相关阅读:
    Delphi中QuotedStr介绍及使用
    <<编写可维护的JavaScript>>之避免使用全局变量
    JavaScript中的继承模式总结(九)
    JavaScript中的继承(原型链)
    Javascript中函数的四种调用方式
    apply()和call()的区别
    在mui中遇到的内容覆盖导航栏的问题
    相等(==)运算符和等同(===)运算符之间的区别
    理解Javascript参数中的arguments对象
    Javascript之类型检测(一)
  • 原文地址:https://www.cnblogs.com/JDFZ-ZZ/p/13485597.html
Copyright © 2020-2023  润新知