Luogu [ZJOI2008] Knight (base ring tree secondary DP method + tree DP)

Link to the original question The
meaning of the question:
Each knight has a knight that cannot play at the same time, and a combat power. Seek maximum combat effectiveness.
Idea:
Similar to a dance party without a boss .
This question constitutes a forest of base ring trees, and taking the maximum value of each base ring tree is the answer.
After disconnecting one edge of each base ring tree ring, a tree is formed. At this time, it is equivalent to the question of a dance party without a boss. When saving a picture, the default relationship is that two people cannot choose at the same time, so you need to force one to choose one instead of the other, to run DP twice, and max. When
saving the picture, there are directed edges, and the edges point to both. can.
Note that the answer will burst int.
Code:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<ll,ll>PLL;
typedef pair<int,int>PII;
typedef pair<double,double>PDD;
#define I_int ll
inline ll read()
{
    
    
    ll x=0,f=1;
    char ch=getchar();
    while(ch<'0'||ch>'9')
    {
    
    
        if(ch=='-')f=-1;
        ch=getchar();
    }
    while(ch>='0'&&ch<='9')
    {
    
    
        x=x*10+ch-'0';
        ch=getchar();
    }
    return x*f;
}
char F[200];
inline void out(I_int x)
{
    
    
    if (x == 0) return (void) (putchar('0'));
    I_int tmp = x > 0 ? x : -x;
    if (x < 0) putchar('-');
    int cnt = 0;
    while (tmp > 0)
    {
    
    
        F[cnt++] = tmp % 10 + '0';
        tmp /= 10;
    }
    while (cnt > 0) putchar(F[--cnt]);
    //cout<<" ";
}
ll ksm(ll a,ll b,ll p)
{
    
    
    ll res=1;
    while(b)
    {
    
    
        if(b&1)res=res*a%p;
        a=a*a%p;
        b>>=1;
    }
    return res;
}
const int inf=0x3f3f3f3f,mod=998244353;
const ll INF = 0x3f3f3f3f3f3f3f3f;
const double PI = atan(1.0)*4;
const int maxn=1e6+100;

int n,w[maxn],fa[maxn];
bool vis[maxn];
ll res;
int h[maxn],idx;
struct node{
    
    
    int e,ne;
}edge[maxn*2];
ll dp[maxn][2];

void add(int u,int v){
    
    
    edge[idx]={
    
    v,h[u]};h[u]=idx++;
}
void DP(int u,int root){
    
    
    vis[u]=1;
    dp[u][0]=0;dp[u][1]=w[u];
    for(int i=h[u];~i;i=edge[i].ne){
    
    
        int j=edge[i].e;
        if(j!=root){
    
    
            DP(j,root);
            dp[u][0]+=max(dp[j][0],dp[j][1]);
            dp[u][1]+=dp[j][0];
        }
        else dp[j][1]=-inf;
    }
}
void dfs(int u){
    
    
    vis[u]=1;
    int root=u;
    while(!vis[fa[root]]){
    
    
        root=fa[root];vis[root]=1;
    }
    DP(root,root);
    ll tmp=max(dp[root][0],dp[root][1]);
    vis[root]=1;root=fa[root];
    DP(root,root);
    tmp=max(tmp,max(dp[root][0],dp[root][1]));
    res+=tmp;
}

int main(){
    
    
    memset(h,-1,sizeof h);
    n=read();
    for(int i=1;i<=n;i++){
    
    
        w[i]=read();///该骑士的战斗力
        int x=read();///i讨厌x
        add(x,i);
        fa[i]=x;
    }
    for(int i=1;i<=n;i++)
        if(!vis[i]) dfs(i);///对每个没访问的点dfs
    printf("%lld\n",res);
	return 0;
}







reference:

Guess you like

Origin blog.csdn.net/weixin_45675097/article/details/110307467