luogu2607/bzoj1040 [ZJOI2008]骑士 (基环树形dp)

N个点,每个点发出一条边,那么这个图的形状一定是一个基环树森林(如果有重边就会出现森林)

那我做f[0][x]和f[1][x]分别表示对于x子树,x这个点选还是不选所带来的最大价值

然后就变成了这好几个环上不能选相邻的点,最大的价值和

我们把这个环从N到1处断开,然后钦定一下1选还是不选,统计一下答案就可以了。

  1 #include<bits/stdc++.h>
  2 #define pa pair<int,int>
  3 #define ll long long
  4 using namespace std;
  5 const int maxn=1000010;
  6
  7 inline ll rd(){
  8     ll x=0;char c=getchar();int neg=1;
  9     while(c<‘0‘||c>‘9‘){if(c==‘-‘) neg=-1;c=getchar();}
 10     while(c>=‘0‘&&c<=‘9‘) x=x*10+c-‘0‘,c=getchar();
 11     return x*neg;
 12 }
 13
 14 int N;
 15 int eg[maxn*2][2],egh[maxn],ect;
 16 int dep[maxn],fa[maxn];
 17 int root[maxn][2],pct,rh[maxn],rct;
 18 int stk[maxn],top[maxn];
 19 ll f[2][maxn];
 20 bool flag[maxn],isroot[maxn],connected[maxn];
 21
 22 inline void adeg(int a,int b){
 23     eg[++ect][0]=b;eg[ect][1]=egh[a];egh[a]=ect;
 24 }
 25 inline void adrot(int a,int b){
 26     root[++rct][0]=b;root[rct][1]=rh[a];rh[a]=rct;
 27 }
 28
 29 void dfs1(int ii,int x){
 30     flag[x]=1;
 31     //printf("%d %d %d\n",x,fa[x],dep[x]);
 32     for(int i=egh[x];i!=-1;i=eg[i][1]){
 33         int b=eg[i][0];if(b==fa[x]) continue;
 34         //printf("#%d %d %d %d %d\n",x,b,flag[b],i,eg[i][1]);
 35         if(flag[b]){
 36             if(connected[ii]) continue;
 37             int u=x,v=b,lca,cnt=0;
 38             if(dep[u]<dep[v]) swap(u,v);
 39             while(dep[u]!=dep[v]) adrot(ii,u),isroot[u]=1,u=fa[u];
 40             while(u!=v){
 41                 isroot[u]=isroot[v]=1;
 42                 adrot(ii,u);
 43                 stk[++cnt]=v;
 44                 u=fa[u];v=fa[v];
 45             }lca=u;isroot[lca]=1;adrot(ii,lca);
 46             for(int j=cnt;j;j--) adrot(ii,stk[j]);
 47             connected[ii]=1;
 48         }else{
 49             dep[b]=dep[x]+1;fa[b]=x;
 50             dfs1(ii,b);
 51         }
 52     }
 53 }
 54
 55 void dfs2(int x,int F){
 56     for(int i=egh[x];i!=-1;i=eg[i][1]){
 57         int b=eg[i][0];if(b==F||isroot[b]) continue;
 58         dfs2(b,x);
 59         f[0][x]+=max(f[0][b],f[1][b]);
 60         f[1][x]+=f[0][b];
 61     }
 62 }
 63
 64 inline ll solve(int p){
 65     if(rh[p]==-1) return max(f[0][top[p]],f[1][top[p]]);
 66     ll re=0;
 67     ll g1=f[1][root[rh[p]][0]],g0=0;
 68     for(int i=root[rh[p]][1];i!=-1;i=root[i][1]){
 69         ll xx=max(g0,g1);
 70         g1=g0+f[1][root[i][0]];
 71         g0=xx+f[0][root[i][0]];
 72     }re=max(re,g0);
 73
 74     g1=0,g0=f[0][root[rh[p]][0]];
 75     for(int i=root[rh[p]][1];i!=-1;i=root[i][1]){
 76         ll xx=max(g0,g1);
 77         g1=g0+f[1][root[i][0]];
 78         g0=xx+f[0][root[i][0]];
 79     }re=max(re,max(g0,g1));
 80     return re;
 81 }
 82
 83 int main(){
 84     int i,j,k;
 85     //freopen("2607.in","r",stdin);
 86     N=rd();memset(egh,-1,sizeof(egh));
 87     for(i=1;i<=N;i++){
 88         int a=rd(),b=rd();
 89         f[1][i]=a;
 90         adeg(i,b);adeg(b,i);
 91     }memset(rh,-1,sizeof(rh));
 92     for(i=1;i<=N;i++){
 93         if(!flag[i]) top[++pct]=i,dfs1(pct,i);
 94     }
 95     //for(i=1;i<=rct;i++) printf("!%d %d %d\n",i,root[i][0],root[i][1]);
 96     for(i=1;i<=rct;i++) dfs2(root[i][0],0);
 97     ll ans=0;
 98     for(i=1;i<=pct;i++){
 99         ans+=solve(i);
100     }
101     printf("%lld\n",ans);
102
103     return 0;
104 }

原文地址:https://www.cnblogs.com/Ressed/p/9648859.html

时间: 2024-10-11 00:05:42

luogu2607/bzoj1040 [ZJOI2008]骑士 (基环树形dp)的相关文章

[BZOJ1040][ZJOI2008]骑士(环套树dp)

1040: [ZJOI2008]骑士 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 5816  Solved: 2263[Submit][Status][Discuss] Description Z国的骑士团是一个很有势力的组织,帮会中汇聚了来自各地的精英.他们劫富济贫,惩恶扬善,受到社会各 界的赞扬.最近发生了一件可怕的事情,邪恶的Y国发动了一场针对Z国的侵略战争.战火绵延五百里,在和平环境 中安逸了数百年的Z国又怎能抵挡的住Y国的军队.于是人

BZOJ_1040_[ZJOI2008]骑士_树形DP

题意: Z国的骑士团是一个很有势力的组织,帮会中汇聚了来自各地的精英.他们劫富济贫,惩恶扬善,受到社会各 界的赞扬.最近发生了一件可怕的事情,邪恶的Y国发动了一场针对Z国的侵略战争.战火绵延五百里,在和平环境 中安逸了数百年的Z国又怎能抵挡的住Y国的军队.于是人们把所有的希望都寄托在了骑士团的身上,就像期待有一 个真龙天子的降生,带领正义打败邪恶.骑士团是肯定具有打败邪恶势力的能力的,但是骑士们互相之间往往有一 些矛盾.每个骑士都有且仅有一个自己最厌恶的骑士(当然不是他自己),他是绝对不会与自己

bzoj1040(ZJOI2008)骑士——基环树

题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1040 基环树的模板. 套路就是把环断开,先把一端作为根节点,强制不选:再把另一端作为根节点,强制不选. 人家的这个判断环的方法真好!还顺便没有连上环的那条边,省下了在函数里判断. 别忘了有多棵基环树! #include<iostream> #include<cstdio> #include<cstring> #define ll long long using n

【环套树+树形dp】Bzoj1040 [ZJOI2008] 骑士

Description Z国的骑士团是一个很有势力的组织,帮会中汇聚了来自各地的精英.他们劫富济贫,惩恶扬善,受到社会各界的赞扬.最近发生了一件可怕的事情,邪恶的Y国发动了一场针对Z国的侵略战争.战火绵延五百里,在和平环境中安逸了数百年的Z国又怎能抵挡的住Y国的军队.于是人们把所有的希望都寄托在了骑士团的身上,就像期待有一个真龙天子的降生,带领正义打败邪恶.骑士团是肯定具有打败邪恶势力的能力的,但是骑士们互相之间往往有一些矛盾.每个骑士都有且仅有一个自己最厌恶的骑士(当然不是他自己),他是绝对不

BZOJ1040:骑士(基环树DP)

Z国的骑士团是一个很有势力的组织,帮会中汇聚了来自各地的精英.他们劫富济贫,惩恶扬善,受到社会各界的赞扬.最近发生了一件可怕的事情,邪恶的Y国发动了一场针对Z国的侵略战争.战火绵延五百里,在和平环境中安逸了数百年的Z国又怎能抵挡的住Y国的军队.于是人们把所有的希望都寄托在了骑士团的身上,就像期待有一个真龙天子的降生,带领正义打败邪恶.骑士团是肯定具有打败邪恶势力的能力的,但是骑士们互相之间往往有一些矛盾.每个骑士都有且仅有一个自己最厌恶的骑士(当然不是他自己),他是绝对不会与自己最厌恶的人一同出

Bzoj1040 [ZJOI2008]骑士

Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 4496  Solved: 1721 Description Z国的骑士团是一个很有势力的组织,帮会中汇聚了来自各地的精英.他们劫富济贫,惩恶扬善,受到社会各界的赞扬.最近发生了一件可怕的事情,邪恶的Y国发动了一场针对Z国的侵略战争.战火绵延五百里,在和平环境中安逸了数百年的Z国又怎能抵挡的住Y国的军队.于是人们把所有的希望都寄托在了骑士团的身上,就像期待有一个真龙天子的降生,带领正义打败邪恶.骑士团

【BZOJ】1040: [ZJOI2008]骑士 环套树DP

[题意]给定n个人的ai和bi,表示第i个人能力值为ai且不能和bi同时选择,求能力值和最大的选择方案.n<=10^6. [算法]环套树DP(基环树) [题解]n个点n条边--基环森林(若干环套树子图). 若原图是树,经典DP做法:f[i][0/1]表示i点选或不选的最大能力值和,则f[i][0]=Σmax{f[j][0],f[j][1]},f[i][1]=Σf[j][0]+a[i],j=son[i]. 找环:dfs到访问过的点,标记环上的一条边. 破环:和普通树上DP唯一的区别是,标记边两端不

【bzoj1040】【zjoi2008】骑士(树形dp)

题目描述 Description Z国的骑士团是一个很有势力的组织,帮会中汇聚了来自各地的精英.他们劫富济贫,惩恶扬善,受到社会各界的赞扬. 最近发生了一件可怕的事情,邪恶的Y国发动了一场针对Z国的侵略战争.战火绵延五百里,在和平环境中安逸了数百年的Z国又怎能抵挡的住Y国的军队.于是人们把所有的希望都寄托在了骑士团的身上,就像期待有一个真龙天子的降生,带领正义打败邪恶. 骑士团是肯定具有打败邪恶势力的能力的,但是骑士们互相之间往往有一些矛盾.每个骑士都有且仅有一个自己最厌恶的骑士(当然不是他自己

1040: [ZJOI2008]骑士~基环外向树dp

Z国的骑士团是一个很有势力的组织,帮会中汇聚了来自各地的精英.他们劫富济贫,惩恶扬善,受到社会各界的赞扬.最近发生了一件可怕的事情,邪恶的Y国发动了一场针对Z国的侵略战争.战火绵延五百里,在和平环境中安逸了数百年的Z国又怎能抵挡的住Y国的军队.于是人们把所有的希望都寄托在了骑士团的身上,就像期待有一个真龙天子的降生,带领正义打败邪恶.骑士团是肯定具有打败邪恶势力的能力的,但是骑士们互相之间往往有一些矛盾.每个骑士都有且仅有一个自己最厌恶的骑士(当然不是他自己),他是绝对不会与自己最厌恶的人一同出