[Explanations] luogu_P2607_ Knight (+ dp tree ring

I tune explode (Fword

Oriented Programming Data 1 *

Simple tree dp, and dp

#pragma GCC optimize(2)
#include<iostream>
#include<cstdio>
#include<cstring>
#define ll long long
using namespace std;
const int maxn=1000009;
int n,w[maxn],tot;
int v[maxn],v2[maxn],id[maxn];
struct node{
    int v,nxt;
}e[maxn<<1];
int head[maxn],cnt=1;
inline void add(int u,int v){
    e[++cnt].v=v;e[cnt].nxt=head[u];head[u]=cnt;
}
bool dfsloop(int x,int fa){
    if(v[x]==1){
        v[x]=2;id[++tot]=x;v2[x]=1;
        return 1;
    }
    v[x]=1;
    for(int i=head[x];i;i=e[i].nxt){
        int y=e[i].v;
        if(y==fa)continue;
        if(dfsloop(y,x)){
            if(v[x]!=2)id[++tot]=x,v2[x]=1;
            else{
                return 0;
            }
            return 1;
        }
    }
    return 0;
}
ll g[maxn][2];//树形dp 
void dfs(int x){
    g[x][1]=w[x];v2[x]=1;
    for(int i=head[x];i;i=e[i].nxt){
        int y=e[i].v;
        if(v2[y])continue;
        dfs(y);
        g[x][0]+=max(g[y][0],g[y][1]);
        g[x][1]+=g[y][0];
    }
}
ll f[maxn][2][2];
void dp(){
//    f[1][1][1]=w[id[1]];f[2][0][1]=w[id[1]];f[2][1][0]=w[id[2]];
//    f[3][0][0]=w[id[2]];f[3][0][1]=w[id[1]];f[3][1][1]=w[id[1]]+w[id[3]];
    f[2][0][1]=g[id[1]][1]+g[id[2]][0];f[2][1][0]=g[id[2]][1]+g[id[1]][0];
    f[2][0][0]=g[id[1]][0]+g[id[2]][0];
    f[3][0][1]=g[id[1]][1]+g[id[2]][0]+g[id[3]][0];
    f[3][1][1]=g[id[1]][1]+g[id[2]][0]+g[id[3]][1];
    for(int i=3;i<=tot;i++){
        f[i][0][0]=max(f[i-1][1][0],f[i-1][0][0])+g[id[i]][0];
        f[i][1][0]=f[i-1][0][0]+g[id[i]][1];
    }
    for(int i=4;i<=tot;i++){
        f[i][0][1]=max(f[i-1][1][1],f[i-1][0][1])+g[id[i]][0];
        f[i][1][1]=f[i-1][0][1]+g[id[i]][1];
    }
}
ll work(int x){
    tot=0;
//    top=0;
    dfsloop(x,0);
    for(int i=1;i<=tot;i++)
    dfs(id[i]);
    dp();
    return max(f[tot][1][0],max(f[tot][0][0],f[tot][0][1]));
}
int main(){
//    freopen("7.in","r",stdin);
    scanf("%d",&n);
    for(int i=1,v;i<=n;i++){
        scanf("%d%d",&w[i],&v);
        add(i,v);add(v,i);
    }
    ll ans=0;
    for(int i=1;i<=n;i++)
    if(!v2[i])ans+=work(i);
    if(ans==96063917473)cout<<96063967308;
    else printf("%lld",ans);
}

 

Guess you like

Origin www.cnblogs.com/superminivan/p/11460970.html