二叉苹果树(有依赖的背包 点权 无向边)
其实是比较多的类型
#include<iostream>
using namespace std;
struct EDGE{
int next;
int to;
int w;
}edge[201];
int head[101];
int dp[101][101];
int tot;
void addedge(int u,int v,int w){
edge[++tot].next=head[u];
edge[tot].to=v;
edge[tot].w=w;
head[u]=tot;
}
int n,q;
void dfs(int u,int father){
for(int i=head[u];~i;i=edge[i].next){
int v=edge[i].to;
if(v==father)continue;
for(int j=q;j>=0;j--){//?
for(int k=0;k<j;k++){
dp[u][j]=max(dp[u][j],dp[v][k]+dp[u][j-k-1]+edge[i].w);
}
}
}
}
int main(){
cin>>n>>q;
for(int i=1;i<=n;i++)head[i]=-1;
for(int i=1;i<=n-1;i++){
int u,v,w;
cin>>u>>v>>w;
addedge(u,v,w);
addedge(v,u,w);
}
dfs(1,0);
cout<<dp[1][q];
}
有依赖的背包问题(有依赖的背包 点权)
#include<iostream>
using namespace std;
#include<cstring>
int n,m;
int f[110][110];
int v[110];
int w[110];
struct EDGE{
int next;
int to;
}edge[110];
int tot;
int head[110];
void add(int u,int v){
edge[++tot].next=head[u];
edge[tot].to=v;
head[u]=tot;
//cout<<u<<" "<<head[9]<<endl;
}
void dfs(int u){
/*for(int j=0;j<v[u];j++){
f[u][j]=0;
}*/
// cout<<"u"<<u<<endl;
for(int j=v[u];j<=m;j++){
f[u][j]=w[u];
}
//cout<<"head"<<head[u]<<endl;
for(int i=head[u];~i;i=edge[i].next){
int son=edge[i].to;
dfs(son);
for(int j=m;j>=v[u];j--){
for(int k=0;k<=j-v[u];k++){
//if(j>=v[u])
f[u][j]=max(f[u][j-k]+f[son][k],f[u][j]);
}
}
}
// cout<<endl;
}
int main(){
cin>>n>>m;
int root;
memset(head,-1,sizeof(head));
for(int i=1;i<=n;i++){
//head[i]=-1;
int p;
cin>>v[i]>>w[i];
cin>>p;
if(p==-1)root=i;
else {
add(p,i);}
}
dfs(root);
cout<<f[root][m];
}
没有上司的舞会(点权 有向边 类似战略游戏)
#include<iostream>
using namespace std;
bool st[6001];
int f[6001][2];
int a[6001];
int head[6001];
int tot=0;
int n;
struct EDge{
int next;
int to;
}edge[6001];
void addedge(int u,int v){
edge[++tot].next=head[u];
edge[tot].to=v;
head[u]=tot;
}
void dfs(int u){
f[u][1]=a[u];
for(int i=head[u];~i;i=edge[i].next){
int v=edge[i].to;
dfs(v);
f[u][0]+=max(f[v][0],f[v][1]);
f[u][1]+=f[v][0];
/*for(int i=1;i<=n;i++){
cout<<f[i][0]<<" "<<f[i][1]<<endl;
}*/
}
}
int main(){
cin>>n;
for(int i=1;i<=n;i++){
cin>>a[i];
head[i]=-1;
}
for(int i=1;i<=n-1;i++){
int u,v;
cin>>v>>u;
addedge(u,v);
st[v]=1;
}
int root=1;
while(st[root])root++;
dfs(root);
/*for(int i=1;i<=n;i++){
cout<<f[i][0]<<" "<<f[i][1]<<endl;
}*/
cout<<max(f[root][0],f[root][1]);
}
战略游戏( 类似没有上司的舞会)
#include<iostream>
using namespace std;
#include<vector>
#include<cstring>
vector<int> g[1501];
bool st[1501];
int f[1501][2];
void dfs(int u){
f[u][1]=1;
for(auto v:g[u]){
dfs(v);
f[u][0]+=f[v][1];
f[u][1]+=min(f[v][1],f[v][0]);
}
}
int main()
{
int n;
while(cin>>n){
for(int i=0;i<=n-1;i++)g[i].clear();
memset(st,0,sizeof(st));
memset(f,0,sizeof(f));
for(int nn=1;nn<=n;nn++){
int m,i;
scanf("%d:(%d)",&i,&m);
while(m--){
int v;
cin>>v;
g[i].push_back(v);
st[v]=1;
}
}
int root=0;
while(st[root])root++;
dfs(root);
cout<<min(f[root][0],f[root][1])<<endl;
}
}
皇宫看守(比舞会、战略游戏状态更多)
之前的错误例子
如果像这样在枚举v1的时候顺便求了f[u][1]是不行的,因为其他点可能还没更新
void dfs(int u){
f[u][2]=w[u];
for(auto v:g[u]){
dfs(v);
f[u][0]+=min(f[v][1],f[v][2]);
f[u][2]+=min(f[v][0],min(f[v][1],f[v][2]));
int sum=f[v][2];
for(auto v1:g[u]){
if(v1==v)continue;
sum+=min(f[v1][1],f[v1][2]);
}
f[u][1]=min(f[u][1],sum);
}
}
#include<iostream>
using namespace std;
#include<vector>
#define INF 0x3f3f3f3f
int n;
vector<int> g[1501];
int w[1501];
int f[1501][3];
bool st[1501];
void dfs(int u){
f[u][2]=w[u];
int sum=0;
for(auto v:g[u]){
// cout<<"dfsv:"<<v<<endl;
dfs(v);
f[u][0]+=min(f[v][1],f[v][2]);
f[u][2]+=min(f[v][0],min(f[v][1],f[v][2]));
/*int sum=f[v][2];
for(auto v1:g[u]){
if(v1==v)continue;
sum+=min(f[v1][1],f[v1][2]);
}
f[u][1]=min(f[u][1],sum);*/
sum+=min(f[v][1],f[v][2]);
}
f[u][1]=INF;
for(auto v:g[u]){
f[u][1]=min(f[u][1],f[v][2]+sum-min(f[v][1],f[v][2]));
//f[v][2]
//sum-min(,)其余点是总的sum减去该点的贡献
}
/*for(int i=1;i<=n;i++){
cout<<f[i][0]<<" "<<f[i][1]<<" "<<f[i][2]<<endl;
}
*/
}
int main()
{
cin>>n;
for(int nn=1;nn<=n;nn++){
int u,m;
cin>>u>>w[u]>>m;
while(m--){
int v;
cin>>v;
g[u].push_back(v);
st[v]=1;
}
}
int root=1;
while(st[root])root++;
//cout<<"**"<<root<<"**"<<endl;
dfs(root);
/*for(int i=1;i<=n;i++){
cout<<f[i][0]<<" "<<f[i][1]<<" "<<f[i][2]<<endl;
}
*/
//cout<<f[root][0]<<" "<<f[root][1]<<" "<<f[root][2]<<endl;
cout<<min(f[root][1],f[root][2]);
}