原题连接:
http://acm.hdu.edu.cn/showproblem.php?pid=2196
思路:
好了,无敌了,经过昨晚4个钟头+今上午1个小时的奋战,这题终于被我AC了
收获的确是不小。。呵呵
一步步的总结吧,题意就是让你求给定树中某一个点到其他任意点的最大权值
(1)总体的思路。一个点到其他任意点的最大权值只有两种可能性,一个是这个值来自的子树,另一个是这个值来自父结点,因为这个点通往外界的出口就只有这两条了。
(2)首先是求出子树的最大权值,这个只需要用一个dfs+记忆化搜索,这里之所以dfs一个根结点就可以得到所有点的f[i][0]是因为,在遍历所有叶子的过程中,它实际就是路过了所有的结点——只有这样才有可能便利到所有的叶子。
(3)其次要求每个节点的f[i][1],即通过自己的父节点能够达到的最大权值,那么这个值有两种可能性。就这一块纠结了能有几个小时,如果在一开始就很严密的给总结好,就不会有那么多的麻烦了。一是父节点的其他分支,(注!如果这个分枝不存在,那么这个值就是w)另一个是父节点的父节点,我们在这两个值中选择一个更大的赋给f[i][1]。
(4)还有一个坑了好久的地方是求某节点到叶子的第二长距离,这个也是要考虑到所有的大小可能性,然后仔细的做好分类
(5)最后说一下这个题的数据结构,即树的存储方式。用了一个struct里面带着两个变量v和w来存储子树和到达子树的距离,然后用一个root数组来存父节点的位置。
(6)last but not least,这个题在网上好像所有人都是用的两个dfs的做法,而我自创了一个dfs+bfs的做法,或许5个h就是代价吧。。。
#include <iostream> #include <vector> #include <cstring> #include <queue> #define MAX 10007 using namespace std; int n; int max(int a,int b) { return a>b?a:b; } struct node { int v,w; }; vector<node> son[MAX]; __int64 f[MAX][3]; __int64 dp[MAX]; int root[MAX]; queue<int> q; int end[MAX]; __int64 dfs1(int s) { if(f[s][0] != -1) return f[s][0]; else { int len = son[s].size(); for(int i = 0;i < len;i++) { int v = son[s][i].v; int w = son[s][i].w; int nn = w+dfs1(v); if(nn>f[s][0]) { if(f[s][0] == f[s][2]) f[s][0] = nn; else { f[s][2] = f[s][0]; f[s][0] = nn; } } else if(nn>f[s][2]) f[s][2] = nn; } return f[s][0]; } } void bfs() { while(!q.empty()) { int s = q.front(); q.pop(); int len = son[s].size(); for(int i = 0;i < len;i++) { int v = son[s][i].v; int w = son[s][i].w; if(f[v][0]+w != f[s][0]) f[v][1] = f[s][0]+w; else { if(f[s][2] != -1) f[v][1] = w+f[s][2]; else f[v][1] = w; } f[v][1] = max(f[v][1],f[s][1]+w); dp[v] = max(f[v][0],f[v][1]); q.push(v); } } } int main() { while(cin>>n) { memset(root,-1,sizeof(root)); for(int i = 1;i <= n;i++) son[i].clear(); int v,w; for(int i = 2;i <= n;i++) { cin>>v>>w; //构建树 node tmp; tmp.v = i; tmp.w = w; son[v].push_back(tmp); root[i] = v; } memset(f,-1,sizeof(f)); for(int i = 1;i <= n;i++) if(son[i].empty()) f[i][0] = 0; //dfs求所有的点到叶子节点的最长距离 dfs1(1); //bfs求所有点的f[i][1] memset(dp,-1,sizeof(dp)); dp[1] = f[1][0];//树根节点已经成为了男人 q.push(1); bfs(); for(int i = 1;i <= n;i++) cout<<dp[i]<<endl; } return 0; }