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;
    }
  • 相关阅读:
    百科知识 scm文件如何打开
    百科知识 STEP文件如何打开
    百科知识 tar文件如何打开
    百科知识 kux文件如何打开
    app开发中如何利用sessionId来实现服务端与客户端保持回话
    什么是云虚拟主机以及和云服务器之间的区别
    2016年百度百科怎么创建词条(高级技巧篇)
    使用Jsoup获取网页内容超时设置
    如何让自己在天猫开通的商铺能够在百度中输入关键词就能够搜索到
    百度百科词条义项排名靠前秘诀
  • 原文地址:https://www.cnblogs.com/popo-black-cat/p/10698267.html
Copyright © 2011-2022 走看看