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\n",ans*K);
    return 0;
}

 

posted @ 2019-04-12 20:08  paopo  阅读(208)  评论(0编辑  收藏  举报