主要问题: 树如何编号(重点:如何体现父子关系)
树的编号方式:
1)读入给了编号并给予父子关系 (父子关系已给出) 处理:同存图
2)将数组转化为一个树 父子关系体现在其编号上(编号的关系->父子关系)典型:线段树,堆(lson:2*x rson: 2*x+1)
void dfs(int x)
{
cin>>a[x].x>>a[x].w;
a[x].x*=2;
if(a[x].w==0)
{
dfs(x*2);dfs(x*2+1);
}
}
3)直接搞dfs序,一边深搜一边编号
void find()
{
cnt++;int x=cnt;
int a,b;cin>>a>>b;
if(b==0)
{
int l=cnt+1,r;find();
r=cnt+1;find();
v[x].push_back(l);v[x].push_back(r);
}
}
Then是完整代码
方法1:dfs序
由于输入的访问次序与dfs序相同,所以直接做一遍dfs找出lson,rson即可,无需额外存储父子关系
#include <iostream>
#include <cstdio>
#include <vector>
using namespace std;
const int maxn=1005;
vector<int> v[maxn];
int f[maxn][maxn];
int cnt=0;
int n;
void find()
{
cnt++;int x=cnt;
int w,val;cin>>w>>val;
w*=2;
if(val==0)
{
int l=cnt+1,r;find();
r=cnt+1;find();
for(int tim=w;tim<=n;tim++)
{
for(int p=0;p<=tim-w;p++)
{
int temp=f[l][p]+f[r][tim-w-p];
f[x][tim]=max(f[x][tim],temp);
}
}
}
else
{
for(int tim=w;tim<=n;tim++)
{
f[cnt][tim]=min(val,(tim-w)/5);
}
}
}
int main()
{
cin>>n;n--;
find();
cout<<f[1][n]<<endl;
return 0;
}
方法2:采用线段树的存储方法(lson=2*x,rson=2*x+1)
此方法可能存在空结点,没有完全利用。
#include <iostream>
#include <cstdio>
#include <vector>
using namespace std;
const int maxn=1005;
struct node
{
int x;int w;
}a[maxn];
int f[maxn][maxn];
int cnt;node k;
void dfs(int x)
{
cin>>a[x].x>>a[x].w;
a[x].x*=2;
if(a[x].w==0)
{
dfs(x*2);dfs(x*2+1);
}
}
int find(int x,int cost)
{
if(cost==0||f[x][cost]) return f[x][cost];
if(a[x].w) return f[x][cost]=min(a[x].w,(cost-a[x].x)/5);
for(int p=0;p<=cost-a[x].x;p++)
{
int temp=find(x*2,p)+find(x*2+1,cost-p-a[x].x);
f[x][cost]=max(f[x][cost],temp);
}
return f[x][cost];
}
int main()
{
int t;scanf("%d",&t);t-=1;
dfs(1);
cnt=0;
cout<<find(1,t)<<endl;
return 0;
}