zoukankan      html  css  js  c++  java
  • P1453 城市环路

      一道环套树,套树dp(十分水)。

      对于环上每一个点,都在子树中dp求出取这个点和不取的值,最后在这个环上强制一条边上的两个点不能同时选,dp两次,取最大值即可。

      虽然貌似知道强制删掉一条边dp一边就可以……但是复杂度是一样的,怎么写开心怎么来!

      一开始0分,因为需要用的数组下标是1,2,然而我就开了2……开3就90……

      最后发现没有暴力删边,加上就AC了……

      代码:

    #include<cstdio>
    #include<queue>
    #include<iostream>
    #include<algorithm>
    #include<cstring>
    using namespace std;
    #define maxn 200005
    typedef double db;
    struct node
    {
        int id,no[3];
        db val;
    } q[maxn];
    int head[maxn],to[maxn],nxt[maxn],fa[maxn];
    db f[maxn][2],us[maxn][2],w[maxn],ans;
    bool inc[maxn],vis[maxn],flag;
    int n,cnt,tot;
    db K;
    void add(int a,int b)
    {
        to[++cnt]=b;
        nxt[cnt]=head[a];
        head[a]=cnt;
    }
    void dfs(int u,int faa)
    {
        if(flag) return ;
        vis[u]=1;
        fa[u]=faa;
        for(int i=head[u]; i; i=nxt[i])
        {
            int v=to[i];
            if(v==faa) continue;
            if(vis[v])
            {
                if(inc[v]) continue;
                int x=u;
                int tmp;
                while(x!=v)
                {
                    q[++tot].id=x;
                    q[tot].val=w[x];
                    inc[x]=1;
                    x=fa[x];
                }
                q[++tot].id=v;
                q[tot].val=w[v];
                inc[v]=1;
                flag=1;
            }
            dfs(v,u);
        }
    }
    void dp(int u,int faa,int o)
    {
        f[u][1]=w[u];
        for(int i=head[u]; i; i=nxt[i])
        {
            int v=to[i];
            if(v==faa) continue;
            if(o)
                if(v==q[o].no[1]||v==q[o].no[2])
                    continue;
            dp(v,u,0);
            f[u][1]+=f[v][0];
            f[u][0]+=max(f[v][0],f[v][1]);
            ans=max(f[u][1],f[u][0]);
        }
    }
    int main()
    {
        scanf("%d",&n);
        for(int i=1; i<=n; i++)
            scanf("%lf",&w[i]);
        for(int i=1; i<=n; i++)
        {
            int a,b;
            scanf("%d%d",&a,&b);
            ++a;
            ++b;
            add(a,b);
            add(b,a);
        }
        scanf("%lf",&K);
        dfs(1,0);
        for(int i=2;i<tot;i++)
        {
            q[i].no[1]=q[i-1].id;
            q[i].no[2]=q[i+1].id;
        }
        q[1].no[1]=q[tot].id;
        q[1].no[2]=q[2].id;
        q[tot].no[1]=q[tot-1].id;
        q[tot].no[2]=q[1].id;
        for(int i=1; i<=tot; i++)
            dp(q[i].id,0,i);
        us[1][1]=f[q[1].id][1];
        us[1][0]=f[q[1].id][0];
        for(int i=2; i<=tot; i++)
        {
            int u=q[i].id;
            us[i][1]=f[u][1];
            us[i][0]=f[u][0];
            us[i][1]+=us[i-1][0];
            us[i][0]+=max(us[i-1][1],us[i-1][0]);
        }
        ans=max(ans,us[tot][0]);
        for(int i=1;i<=tot;i++)
        us[i][0]=us[i][1]=0;
        us[1][1]=-999999999.0;
        us[1][0]=f[q[1].id][0];
        for(int i=2; i<=tot; i++)
        {
            int u=q[i].id;
            us[i][1]=f[u][1];
            us[i][0]=f[u][0];
            us[i][1]+=us[i-1][0];
            us[i][0]+=max(us[i-1][1],us[i-1][0]);
        }
        ans=max(ans,max(us[tot][1],us[tot][0]));
        printf("%.1lf
    ",ans*K);
        return 0;
    }
  • 相关阅读:
    呵呵,庆祝偶的blog开张了~
    把.NET程序部署到没有安装.NETFramwork的机器上
    1842005 日记
    So In Love
    windows网络编程经典入门
    水木穿梭
    c++智能指针的使用,shared_ptr,unique_ptr,weak_ptr
    c++的左值(lvalue),右值(rvalue),移动语义(move),完美转发(forward)
    (一)深入理解JVM第三版JDK的发展历史
    处理在多参数情况下分页参数的完整性
  • 原文地址:https://www.cnblogs.com/popo-black-cat/p/10698267.html
Copyright © 2011-2022 走看看