hdu 2196 Computer(树dp)
来源:互联网 发布:电脑网络不通怎么检查 编辑:程序博客网 时间:2024/06/05 07:53
题意:
给出n个点, n-条边,每条边有权值,问从每个点出发能得到的最大值,不返回。
解题思路:
第一道树dp。
树dp的话只不过是转移的关系是在当前节点和几个孩子节点上,也就是从孩子节点转移到当前节点,但由于是一棵树,当前节点的父节点其实也是自己的一个前驱,也可以从父亲节点转移到当前节点,树dp比较麻烦的就是这一步了。
这道题,一个节点出发的最大值的路径无非就是过父亲节点,过孩子节点两种情况。
假设1是根,我们dfs一遍递归处理处每个节点到儿子节点能产生的最大值。
然后再第二遍dfs,将第一遍求得的到儿子节点的最大值和父亲节点出发得到的最大值(这个时候已经求出)比较一下,如果是连接当前节点的边权w+父亲最大值大于当前最大值,那么就更新一下。
然后,有个问题,如果父亲的最大值的情况是过当前节点不就不对了嘛。所以要求出父亲节点不过当前节点的最大值,假如父亲的最大值过了当前节点,那么我们需要一个次大值,而这个值就一定保证了不会过当前节点,就可以转移了。大约树dp比较难的都是这一步??
代码:
#include <bits/stdc++.h>#define ps push_back#define fir first#define sec secondusing namespace std;const int maxn=1e4+5;//vector<pair<int, int> >edg[maxn];struct node{ int to; int w; int nex;}edg[maxn*10];int cnt;int head[maxn];void add(int u, int v, int w){ edg[cnt].to=v; edg[cnt].w=w; edg[cnt].nex=head[u]; head[u]=cnt++;}int ma[maxn];int mato[maxn];int sma[maxn];int smato[maxn];int n;void dfs1(int x, int fa){ int i, to, w;// for(i=0; i<(int)edg[x].size(); i++) for(i=head[x]; i!=-1; i=edg[i].nex) {// to=edg[x][i].fir, w=edg[x][i].sec; to=edg[i].to, w=edg[i].w; if(to==fa)continue; dfs1(to, x);// printf("%d %d %d %d %d\n", x, to, ma[x], ma[to], w); if(sma[x]<ma[to]+w) { sma[x]=ma[to]+w; smato[x]=to; if(sma[x]>ma[x]) { swap(sma[x], ma[x]); swap(smato[x], mato[x]); } } } return;}void dfs2(int x, int fa, int w){ if(x!=1) { if(mato[fa]!=x) { // printf("%d %d %d %d %d\n", x, fa, w, ma[fa], ma[x]); if(ma[fa]+w>sma[x]) { sma[x]=ma[fa]+w; smato[x]=fa; if(sma[x]>ma[x]) { swap(sma[x], ma[x]); swap(mato[x], smato[x]); } } } else { // printf("*%d %d %d %d %d\n", x, fa, w, sma[fa], ma[x]); if(sma[fa]+w>sma[x]) { sma[x]=sma[fa]+w; smato[x]=fa; if(sma[x]>ma[x]) { swap(sma[x], ma[x]); swap(mato[x], smato[x]); } } } } int to, ww;// for(int i=0; i<(int)edg[x].size(); i++) for(int i=head[x]; i!=-1; i=edg[i].nex) { to=edg[i].to, ww=edg[i].w; if(to==fa)continue; dfs2(to, x, ww); } return;}int main(){ while(~scanf("%d", &n)) { cnt=0; for(int i=0; i<=n; i++) { ma[i]=mato[i]=sma[i]=0; head[i]=-1; } int x, y; pair<int, int>pa; for(int i=2; i<=n; i++) { scanf("%d%d", &x, &y); //pa.second=y, pa.fir=i; add(x, i, y); //edg[x].ps(pa); } dfs1(1, 0); dfs2(1, 0, 0); for(int i=1; i<=n; i++)printf("%d\n", ma[i]); }}
阅读全文
0 0
- hdu 2196 Computer(树dp)
- hdu 2196 Computer DP
- hdu 2196 Computer(树dp)
- HDU - 2196 Computer 经典树型DP
- HDU-2196 Computer(树dp)
- HDU 2196 Computer (树型dp/树直径)
- HDU 2196 Computer(树形dp)
- 【树形DP】 HDU 2196 Computer
- HDU 2196 Computer(树形DP)
- Hdu 2196 Computer(树形dp)
- Computer - HDU 2196 树形dp
- Hdu 2196 Computer (树形dp)
- HDU 2196 Computer | 树形dp
- 【树形DP】 HDU 2196 Computer
- HDU 2196 Computer (树形DP)
- hdu 2196 computer 树状dp
- hdu 2196 Computer (树形dp)
- *HDU 2196 - Computer(树形DP)
- 152. Maximum Product Subarray dynamic programming
- java:String使用equals和==比较的区别
- 深度强化学习中的DQN系列算法
- JSP&Servlet6(二) --- JSP标准标签
- gflags学习
- hdu 2196 Computer(树dp)
- 1007. 小黄车
- 拦截器
- Bash Scripts ---part1
- 多线程并发执行任务,取结果归集。终极总结:Future、FutureTask、CompletionService、CompletableFuture
- Swing 中如何获取JTestField中的内容 并且 点击按钮输出
- 转发与重定向的区别
- 文章标题
- 一个屌丝程序猿的人生(四)