树形DP和状压DP
P1352 没有上司的舞会
作为一道经典例题,几乎学树形
设
#include<bits/stdc++.h>
using namespace std;
int dp[200020][2];
int n;
int h[200003];
struct node{
int to,nxt;
}z[200003];
int cnt;
void add(int a,int b){
z[++cnt].to=b;
z[cnt].nxt=h[a];
h[a]=cnt;
}
int a[200003];
void dfs(int now,int fa){
dp[now][0]=0;
dp[now][1]=a[now];
for(int i=h[now];i;i=z[i].nxt){
int y=z[i].to;
if(y==fa) continue;
else{
dfs(y,now);
dp[now][0]+=max(dp[y][0],dp[y][1]);
dp[now][1]+=dp[y][0];
}
}
}
int in[200003];
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
for(int i=1;i<n;i++) {
int k,l;
scanf("%d%d",&l,&k);
add(k,l);
in[l]++;
}
int boss;
for(int i=1;i<=n;i++) if(!in[i]){ boss=i;break; }
dfs(boss,0);
cout<<max(dp[boss][1],dp[boss][0]);
}
P2014 [CTSC1997] 选课
其实就是一个
设
对于点
#include<bits/stdc++.h>
using namespace std;
struct node{
int nxt,to;
}z[305];
int n,m,cnt;
int h[305];
int dp[305][304];
void add(int u,int v){
cnt++;
z[cnt].nxt=h[u];
z[cnt].to=v;
h[u]=cnt;
}
void dfs(int x){
for(int i=h[x];i;i=z[i].nxt){
int y=z[i].to;
dfs(y);
for(int j=m;j>=1;j--){
for(int k=0;k<j;k++){
dp[x][j]=max(dp[x][j],dp[x][j-k]+dp[y][k]);
}
}
}
}
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++){
int a,b;
scanf("%d%d",&a,&dp[i][1]);
add(a,i);
}
m++;
dfs(0);
printf("%d",dp[0][m]);
}
P3478 [POI2008] STA-Station
我们可以先从第
然后再来一遍
#include<bits/stdc++.h>
#define int long long
using namespace std;
int n;
struct node{
int to,nxt;
}z[2000004];
int h[1000004];
int cnt;
void add(int x,int y){
z[++cnt].to=y;
z[cnt].nxt=h[x];
h[x]=cnt;
}
int dep[1000004];
int siz[1000004];
int sum_dep[1000005];
void dfs(int x,int fa){
siz[x]=1;
dep[x]=dep[fa]+1;
for(int i=h[x];i;i=z[i].nxt ){
int y=z[i].to;
if(y==fa) continue;
else{
dfs(y,x);
siz[x]+=siz[y];
}
}
}
int f[1000004];
void DFS(int x,int fa){
for(int i=h[x];i;i=z[i].nxt){
int y=z[i].to;
if(y==fa) continue;
else{
f[y]=f[x]-1ll*2*siz[y]+n;
DFS(y,x);
}
}
}
signed main(){
scanf("%lld",&n);
for(int i=1;i<n;i++){
int u,v;
scanf("%lld%lld",&u,&v);
add(u,v);
add(v,u);
}
dfs(1,0);
int t;
int maxx=0;
for(int i=1;i<=n;i++) f[1]+=dep[i];
DFS(1,0);
for(int i=1;i<=n;i++){
//maxx=max(maxx,f[i]);
if(maxx<f[i]){
maxx=f[i];
t=i;
}
}
cout<<t<<endl;
}
P2607 [ZJOI2008] 骑士
这是一颗基环树,所以我们肯定不能上来就做。
我们可以先找到环,然后跑两次
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e6+10;
int f[N][2];
int val[N];
int n;
struct node{
int to,nxt;
}z[2*N];
int cnt;
int h[N];
int F[N];
int vis[N];
void add(int x,int y){
z[++cnt].to=y;
z[cnt].nxt=h[x];
h[x]=cnt;
}
int root;
void dp(int x){
f[x][0]=0;
f[x][1]=val[x];
vis[x]=1;
for(int i=h[x];i;i=z[i].nxt){
int y=z[i].to;
if(y!=root){
dp(y);
f[x][0]+=max(f[y][0],f[y][1]);
f[x][1]+=f[y][0];
}
else{
f[y][1]=-1e9;
}
}
}
int ans;
void Find(int x){
root=x;
vis[x]=1;
while(!vis[F[root]]){
root=F[root];
vis[root]=1;
}
dp(root);
int t=max(f[root][1],f[root][0]);
vis[root]=1;
root=F[root];
dp(root);
ans+=max(t,max(f[root][1],f[root][0]));
}
signed main(){
cin>>n;
for(int i=1;i<=n;i++){
int fa;
cin>>val[i]>>fa;
F[i]=fa;
add(fa,i);
}
for(int i=1;i<=n;i++){
if(!vis[i]){
Find(i);
}
}
cout<<ans;
}
P1896 [SCOI2005] 互不侵犯
一道很普通的状压 DP。
首先预处理出所有状态(即代码中的
然后定义
#include<bits/stdc++.h>
#define int long long
using namespace std;
int n,K;
int sum_s[20090];
int f[10][120][100];
int cnt;
int s[20004];
void dfs(int x,int sum,int y){
if(y>=n){
s[++cnt]=x;
sum_s[cnt]=sum;
return ;
}
dfs(x,sum,y+1);
dfs(x+(1<<y),sum+1,y+2); //因为两个King不能相邻
}
signed main(){
cin>>n>>K;
dfs(0,0,0);
for(int i=1;i<=cnt;i++) f[1][i][sum_s[i]]=1;
for(int i=2;i<=n;i++){
for(int j=1;j<=cnt;j++){
for(int k=1;k<=cnt;k++){
if(s[j]&s[k]) continue;
if((s[j]<<1)&s[k]) continue;
if(s[j]&(s[k]<<1)) continue;
for(int p=K;p>=sum_s[j];p--){
f[i][j][p]+=f[i-1][k][p-sum_s[j]];
}
}
}
}
int ans=0;
for(int i=1;i<=cnt;i++) ans+=f[n][i][K];
cout<<ans;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效