阻击
思路:
该题主要是求树的直径,可参考:树的直径 - OI Wiki (oi-wiki.org)
除此之外,还要维护图中的边(这部分可以用线段树之类的数据结构进行优化)
待优化代码:
#include <bits/stdc++.h>
using namespace std;
typedef pair<int, int> PII;
const int N = 3010;
int n, m;
vector<int> nex[N]; // 邻接表存储图
PII g[N]; // g[i]表示第i条边的起点和终点
int edge[N][N], W[N]; // W[i]表示第i条边的收益, 用于在事件发生后维护整个图
int d1[N], d2[N];
int ans = 0;
// 转换为求树的直径: 用树形dp
void dfs(int u, int fa)
{
d1[u] = d2[u] = 0;
for(int v : nex[u])
{
if(v == fa) continue;
dfs(v, u);
int t = d1[v] + edge[u][v];
if(t > d1[u])
{
d2[u] = d1[u];
d1[u] = t;
}
else if(t > d2[u])
d2[u] = t;
}
ans = max(ans, d1[u] + d2[u]);
}
int main()
{
cin >> n >> m;
int u, v, w, b;
for(int i = 1; i < n; i++ )
{
cin >> u >> v >> w >> b;
edge[u][v] = b - w;
edge[v][u] = b - w;
W[i] = w;
nex[u].push_back(v), nex[v].push_back(u);
g[i] = {u, v};
}
dfs(1, 0);
cout << ans << endl;
int x, y;
for(int i = 0; i < m; i++ )
{
cin >> x >> y;
u = g[x].first, v = g[x].second;
edge[u][v] += W[x] - y;
edge[v][u] += W[x] - y;
W[x] = y;
ans = 0;
dfs(1, 0);
cout << ans << endl;
}
return 0;
}