树形dp开学

来源:互联网 发布:windows清理助手下载 编辑:程序博客网 时间:2024/05/22 05:27

小细节:树形dp有很多求直径的题,关于树的直径,一般是跑两边bfs,但是只能是边权为正时才正确,边权为负无法保证正确性


hdu1520 水,就不多说了

#include<cstdio>#include<algorithm>#include<cstring>#include<string>#include<cmath>using namespace std;struct aa{int pre,to;}edge[100090];int f[60090][2],a[60090],n,tot,head[60090],fa[60090];void addedge(int a,int b){tot++;edge[tot].to=b;edge[tot].pre=head[a];head[a]=tot;}void dfs(int u){f[u][1]=a[u];for (int i=head[u];i;i=edge[i].pre){int v=edge[i].to;dfs(v);f[u][0]+=max(f[v][0],f[v][1]);f[u][1]+=f[v][0];}}int main(){while (~scanf("%d",&n)){for (int i=1;i<=n;i++) scanf("%d",&a[i]);int k,l;tot=0;memset(fa,0,sizeof(fa));memset(head,0,sizeof(head));memset(f,0,sizeof(f));while (scanf("%d%d",&l,&k),k!=0) fa[l]=k;for (int i=1;i<=n;i++) addedge(fa[i],i);dfs(0);printf("%d\n",f[0][0]);}return 0;}

hdu2196

一个有N个结点的树,给你相邻两个结点的距离,问你对于第i个结点,树中离i最远的结点的距离是多少。

这道题,让我真正意识到树形dp的神奇,

dp【i】【1】是到叶子第一远距离,dp【i】【2】是第二远,题中只需要这两个

dp【i】【0】表示它父亲这一支最远距离,由dp【fa【i】】【0】和dp【fa【i】】【1或2】推出

第一遍dfs求出到叶子的第一第二远距离

第二遍dfs求出父亲那一支的最远距离,实际上是跟祖先的最远距离有关,所以第一遍要先求出叶子的最远距离

(通过父亲推孩子节点)

#include<cstdio>#include<cstring>#include<cmath>#include<algorithm>using namespace std;int dp[10009][3],n,head[10009],tot,fa[10009],big[10009],fdis[100009];struct aa{int pre,val,to;}edge[30009];void addedge(int a,int b,int c){tot++;edge[tot].to=b;edge[tot].pre=head[a];head[a]=tot;edge[tot].val=c;}void dfs1(int u,int father){fa[u]=father;for (int i=head[u];i;i=edge[i].pre)if (edge[i].to!=fa[u]){int v=edge[i].to;dfs1(v,u);fdis[v]=edge[i].val;if (dp[u][1]<dp[v][1]+edge[i].val) swap(dp[u][1],dp[u][2]),dp[u][1]=dp[v][1]+edge[i].val,big[u]=v;else if (dp[u][2]<dp[v][1]+edge[i].val) dp[u][2]=dp[v][1]+edge[i].val;}}void dfs2(int u){dp[u][0]=fdis[u]+max(dp[fa[u]][0],u==big[fa[u]]? dp[fa[u]][2]:dp[fa[u]][1]);for (int i=head[u];i;i=edge[i].pre)if (edge[i].to!=fa[u]) dfs2(edge[i].to);}int main(){ while (scanf("%d",&n)!=EOF) { tot=0; memset(head,0,sizeof(head)); memset(dp,0,sizeof(dp)); int l,k; for (int i=2;i<=n;i++) scanf("%d%d",&l,&k),addedge(i,l,k),addedge(l,i,k); dfs1(1,0); dfs2(1); for (int i=1;i<=n;i++) printf("%d\n",max(dp[i][1],dp[i][0]));}return 0;}



0 0
原创粉丝点击