标签:p2 ch 洛谷 int P3761 edge TJOI2017 maxd2 maxd
题目链接
解析
删掉一条边后原树变成两棵树,再连一条边后新树的直径一定不小于这两棵树的直径
考虑再新增一条边,要想新树直径最小,一定是将两树的“中心”相连,经过这条连边的最长路径为两树半径之和加上这条边的长度
枚举修改哪条边,求出断开这条边后两棵树的直径和半径即可统计答案
计算直径一遍\(dp\),同时处理出每个点\(u\)代表的子树中到该点的最长链\(maxd[u]\)和次长链\(maxd2[u]\)
计算半径再一遍\(dfs\),记录从子树外到该点的最长链\(up\),将\(max(maxd[u], up)\)和当前半径取个\(min\),到儿子的\(up\)为\(max(up, maxd[u])+edge.cost\),但注意当最长链经过该儿子时要换成次长链
复杂度\(O(n^2)\),\(5000\)的数据+\(3s\)的时限,常数小点,比如不要\(vector\)存边(说的就是我),可以过
代码
#include <cstdio>
#include <cstring>
#include <iostream>
#include <vector>
#define getv(x, y) (edge[y].u == x ? edge[y].v : edge[y].u)
#define MAXN 5005
typedef long long LL;
const int inf = 0x3f3f3f3f;
struct Edge {
int v, next, cost;
Edge(int _v = 0, int _n = 0, int _c = 0):v(_v), next(_n), cost(_c) {}
} edge[MAXN << 1];
int N, ans = 0x3f3f3f3f;
int dist[MAXN], maxd[MAXN], maxd2[MAXN], head[MAXN], cnt, x[MAXN], y[MAXN], c[MAXN];
char vis[MAXN];
void calc(int, int &, int &);
void dfs(int, int &);
void dfs2(int, int &, int);
void add_edge(int, int, int);
char gc();
int read();
int main() {
memset(head, -1, sizeof head);
N = read();
for (int i = 1; i < N; ++i) {
x[i] = read(), y[i] = read(), c[i] = read();
add_edge(x[i], y[i], c[i]);
add_edge(y[i], x[i], c[i]);
}
for (int i = 1; i < N; ++i) {
int d1 = 0, r1 = inf, d2 = 0, r2 = inf;
vis[y[i]] = 1;
calc(x[i], d1, r1);
vis[x[i]] = 1, vis[y[i]] = 0;
calc(y[i], d2, r2);
vis[x[i]] = 0;
ans = std::min(ans, std::max(std::max(d1, d2), r1 + r2 + c[i]));
}
printf("%d\n", ans);
return 0;
}
void calc(int rt, int &d, int &r) {
dist[rt] = 0;
dfs(rt, d);
dfs2(rt, r, 0);
}
void dfs(int u, int &d) {
maxd[u] = 0, maxd2[u] = -inf;
vis[u] = 1;
for (int i = head[u]; ~i; i = edge[i].next) {
const Edge &e = edge[i];
if (vis[e.v]) continue;
dist[e.v] = dist[u] + e.cost;
dfs(e.v, d);
int tmp = maxd[e.v] + e.cost;
if (tmp > maxd[u]) maxd2[u] = maxd[u], maxd[u] = tmp;
else if (tmp > maxd2[u]) maxd2[u] = tmp;
}
vis[u] = 0;
d = std::max(d, maxd[u] + maxd2[u]);
}
inline char gc() {
static char buf[1000000], *p1, *p2;
if (p1 == p2) p1 = (p2 = buf) + fread(buf, 1, 1000000, stdin);
return p1 == p2 ? EOF : *p2++;
}
inline int read() {
int res = 0; char ch = gc();
while (ch < '0' || ch > '9') ch = gc();
while (ch >= '0' && ch <= '9') res = (res << 1) + (res << 3) + ch - '0', ch = gc();
return res;
}
void dfs2(int u, int &r, int up) {
vis[u] = 1;
r = std::min(r, std::max(up, maxd[u]));
for (int i = head[u]; ~i; i = edge[i].next) {
const Edge &e = edge[i];
if (vis[e.v]) continue;
if (maxd[u] == maxd[e.v] + e.cost) dfs2(e.v, r, std::max(up, maxd2[u]) + e.cost);
else dfs2(e.v, r, std::max(up, maxd[u]) + e.cost);
}
vis[u] = 0;
}
inline void add_edge(int u, int v, int c) { edge[cnt] = Edge(v, head[u], c), head[u] = cnt++; }
//Rhein_E
标签:p2,ch,洛谷,int,P3761,edge,TJOI2017,maxd2,maxd 来源: https://www.cnblogs.com/Rhein-E/p/10461658.html
本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享; 2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关; 3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关; 4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除; 5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。