您的位置:首页 > 其它

HDU 2196 Computer(树形dp经典)

2016-03-09 20:57 239 查看
原题链接

题意:

给出一棵树,求离每个节点最远的点的距离。

Sample Input

5

1 1

2 1

3 1

1 1

Sample Output

3

2

3

4

4

思路:

对于任意一个节点,要寻找其的最远距离的点,则有两种可能。对其子树的子节点的查找,对于其父节点的查找,各自找到其最远距离的节点,并比较两者的大小,即可得到最远距离的节点。

实现:

[i][0],表示顶点为i的子树的,距顶点i的最长距离

f[i][1],表示Tree(i的父节点)-Tree(i)的最长距离+i跟i的父节点距离

子节点查找:要求所有的f[i][0]很简单,只要先做一次dfs求每个结点到叶子结点的最长距离即可。然后要求f[i][1], 可以从父节点递推到子节点,

父节点查找:假设节点u有n个子节点,分别是v1,v2…vn。

如果vi不是u最长距离经过的节点,f[vi][1] = dist(vi,u)+max(f[u][0], f[u][1])

如果vi是u最长距离经过的节点,那么不能选择f[u][0],因为这保存的就是最长距离,要选择Tree(u)第二大距离secondDist。

综上f[vi][1] = dist(vi, u) + max(secondDist, f[u][1])

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<vector>
#include<queue>
#include<cmath>
#include<cstring>
using namespace std;

typedef long long int64;
const int INF = 0x3f3f3f3f;
const double PI  = acos(-1.0);

const int MAXN = 10010;

struct Node{
int v, w;
};

vector<Node>adj[MAXN];

int indeg[MAXN];
int val[MAXN];
int n, m;
int64 f[MAXN][2];
int vis[MAXN];

int64 dfs1(int u){
vis[u] = true;
f[u][0] = 0;
for(int i=0; i<adj[u].size(); ++i){
int v = adj[u][i].v;
int w = adj[u][i].w;
if(vis[v]) continue;
f[u][0] = max(f[u][0], dfs1(v)+w);
}
return f[u][0];
}

void dfs2(int u, int fa_w){
vis[u] = true;

int max1=0, v1, max2=0, v2;

for(int i=0; i<adj[u].size(); ++i){
int v = adj[u][i].v;
int w = adj[u][i].w;
if(vis[v]) continue;
int tmp = f[v][0] + w;
if(tmp > max1){
max2 = max1; v2 = v1;
max1 = tmp; v1 = v;
}else if(tmp == max1 || tmp>max2){
max2 = tmp;
v2 = v;
}
}

if(u != 1){
int tmp = f[u][1];
int v = -1;
if(tmp > max1){
max2 = max1; v2 = v1;
max1 = tmp; v1 = v;
}else if(tmp == max1 || tmp>max2){
max2 = tmp;
v2 = v;
}
}

for(int i=0; i<adj[u].size(); ++i){
int v = adj[u][i].v;
int w = adj[u][i].w;
if(vis[v]) continue;
if(v==v1){
f[v][1] = max2 + w;
}else{
f[v][1] = max1 + w;
}
dfs2(v, w);
}
}

int main(){

while(~scanf("%d", &n) && n){

for(int i=1; i<=n; ++i) adj[i].clear();

for(int u=2; u<=n; ++u){
int v, w;
scanf("%d%d", &v, &w);
adj[u].push_back((Node){v, w});
adj[v].push_back((Node){u, w});
}

memset(f, 0, sizeof(f));

memset(vis, 0, sizeof(vis));
dfs1(1);

memset(vis, 0, sizeof(vis));
dfs2(1, 0);

for(int i=1; i<=n; ++i){
cout << max(f[i][0], f[i][1]) << endl;
}
}

return 0;
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  dp