题目链接:http://tzcoder.cn/acmhome/problemdetail.do?method=showdetail&id=6721
前置知识:树的DFS
思路:最大的收获利益我们考虑使用某个苹果的成熟值和一条以它为端点的最长路径。取1号点为根作dfs,记录每个点到叶节点的最远距离mx和次远距离mx2,记录 son :这个点最远距离是从哪个子节点转移过来的。
然后再做一次dfs,从1号点开始,dfs到每个节点u时,对他的子节点v进行转移,如果最长路不是从这个节点转移过来的则记录这条路径mx3[v]为mx[u],否则则从次长路转移mx3[v]=mx2[u]。
(因为对于每个节点,次长路与最长路一定不是从同一个子节点转移过来的)。
同时比较mx3[u]+1与mx3[v]的大小,如果u的路径3长于v,则令mx3[v]=mx3[u]+1。
(mx1路径是从子节点转移而来的最长路)
(mx2路径是从子节点转移而来的次长路)
(mx3路径是从父节点转移而来的最长路)
问:为什么不用父节点次长路?
答:因为父节点唯一。
code:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int INF = 1e18;
typedef pair<int, int> PII;
const int maxn = 2005;
const int N = 2e5 + 1;
ll n, m, k, H;
vector<int>v[N];
ll a[N];
ll mx[N], mx2[N],mx3[N], ans[N];
ll son[N];
void dfs(int u, int f)
{
for (auto c : v[u])
{
if (c != f)
{
dfs(c, u);
if (mx[u] < mx[c] + 1)
{
mx2[u] = mx[u];
mx[u] = mx[c] + 1;
son[u] = c;
}
else if (mx2[u] < mx[c] + 1)
{
mx2[u] = mx[c] + 1;
}
}
}
}
void dfs2(int u, int f)
{
for (auto c : v[u])
{
if (c != f)
{
if (son[u] != c)
mx3[c] = mx[u] + 1;
else
mx3[c] = mx2[u] + 1;
mx3[c] = max(mx3[u] + 1, mx3[c]);
dfs2(c, u);
}
}
}
inline void solve() {
cin >> n;
for (int i = 1; i < n; i++)
{
int x, y; cin >> x >> y;
v[x].push_back(y);
v[y].push_back(x);
}
for (int i = 1; i <= n; i++)cin >> a[i];
dfs(1, 0);
dfs2(1, 0);
ll ans = 0;
for (int i = 1; i <= n; i++)
ans = max(ans, a[i] * max({ mx[i], mx2[i], mx3[i] }));
cout << ans << endl;
}
signed main() {
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int t = 1;
//cin >> t;
while (t--)
solve();
return 0;
}