话说这是去年大爷的一道NOIP模拟赛题,对着大爷的代码看了一堂课的我终于把这题写掉了。

本题要求在基环树给定的环上删去一条边使剩下的树的直径最小,输出这个最小直径。

那么基环树可以画成这样子的:

有一些在环上的点,还有一些不在环上的点,显然只能在环上断边,我们预处理找出这个环$a_1 - a_m$,然后处理出环上的每一条边的权值$eVal_i$。

先考虑怎么找环,可以用一个栈记录一下系统栈中的元素,当再一次走到一个已经走过的结点的时候把栈里的元素一个一个弹出直到当前元素出栈为止,然后这些元素就是环上的点。

因为要在环上断边,不妨先断开$a_1$和$a_m$之间的边,然后我们预处理四个值$s0_i, s1_i, t0_i, t1_i$,$s0_i$表示从$a_1$开始在环上按照$1, 2, 3, ..., m$的顺序走走到边$a_i, a_{i + 1}$之前能走的最长路径,$s1_i$表示从$a_n$开始走$m, m -  1, m - 2, ..., 1$走到边$a_{i}, a_{i - 1}$之前能走到的最长路径,$t0_i$表示断开边$a_i, a_{i + 1}$$a_1$所在的联通块的直径,$t1_i$则表示断开边$a_{i}, a_{i - 1}$$a_n$所在的联通块的直径,这样子我们枚举一下环上的断边,用$max(t0_i, t1_{i + 1}, eVal_m + s0_i + s1_{i + 1})$更新答案即可。

考虑一下怎么计算$s$和$t$,我们依然可以预处理出从每一个环上的点($a_i = x$)开始不经过环上的点所能走到的最长链$fir_x$和直径$mx_i$,事实上,我们只要顺便计算一下次长链就可以算出直径,所以这些东西可以在一趟$dfs$里解决掉。

我们可以从小到大枚举$1-m$,然后记录一下环上走过的路径,然后顺便用沿路可能出现的最优解更新答案,其实$ans$的初值应该是$t0_m$所以在循环的时候应该注意在这趟循环中循环到$m$,要不然输出$0$……

$t$的计算方法同理。

然后就是码码码,感觉细节巨多。

时间复杂度$O(n)$。

Code:

#include <cstdio>
#include <cstring>
using namespace std;
typedef long long ll; const int N = 2e5 + ; int n, m = , tot = , head[N], a[N], top = , sta[N];
ll fir[N], sec[N], mx[N], s0[N], s1[N], t0[N], t1[N], eVal[N];
bool vis[N], in[N]; struct Edge {
int to, nxt;
ll val;
} e[N << ]; inline void add(int from, int to, ll val) {
e[++tot].to = to;
e[tot].val = val;
e[tot].nxt = head[from];
head[from] = tot;
} template <typename T>
inline void read(T &X) {
X = ; char ch = ; T op = ;
for(; ch > '' || ch < ''; ch = getchar())
if(ch == '-') op = -;
for(; ch >= '' && ch <= ''; ch = getchar())
X = (X << ) + (X << ) + ch - ;
X *= op;
} template <typename T>
inline T max(T x, T y) {
return x > y ? x : y;
} template <typename T>
inline T min(T x, T y) {
return x > y ? y : x;
} template <typename T>
inline void chkMax(T &x, T y) {
if(y > x) x = y;
} template <typename T>
inline void chkMin(T &x, T y) {
if(y < x) x = y;
} bool getCir(int x, int fat) {
if(vis[x]) {
for(; ; ) {
int now = sta[top];
in[now] = ;
a[++m] = now;
--top;
if(now == x) return ;
}
} vis[x] = ; sta[++top] = x;
int tmp = top;
for(int i = head[x]; i; i = e[i].nxt) {
int y = e[i].to;
if(y == fat) continue;
if(getCir(y, x)) return ;
top = tmp;
} return ;
} void getEval(int x, int to) {
if(to == m + ) return;
for(int i = head[x]; i; i = e[i].nxt) {
int y = e[i].to;
if(y != a[to + ]) continue;
eVal[to] = e[i].val;
getEval(y, to + );
}
} ll getMx(int x, int fat) {
ll res = 0LL;
for(int i = head[x]; i; i = e[i].nxt) {
int y = e[i].to;
if(y == fat || in[y]) continue; ll tmp = getMx(y, x), now = fir[y] + e[i].val; chkMax(res, tmp);
if(now > fir[x]) sec[x] = fir[x], fir[x] = now;
else if(now > sec[x]) sec[x] = now;
}
chkMax(res, fir[x] + sec[x]);
return res;
} int main() {
// freopen("tube2.in", "r", stdin); read(n);
for(int i = ; i <= n; i++) {
int x, y; ll v;
read(x), read(y), read(v);
add(x, y, v), add(y, x, v);
} getCir(, );
a[m + ] = a[]; /* for(int i = 1; i <= m; i++)
printf("%d ", a[i]);
printf("\n"); */ getEval(a[], ); /* for(int i = 1; i <= m; i++)
printf("%lld ", eVal[i]);
printf("\n"); */ for(int i = ; i <= m; i++)
mx[i] = getMx(a[i], ); /* for(int i = 1; i <= m; i++)
printf("%lld ", mx[i]);
printf("\n"); */ ll tmp = 0LL;
for(int i = ; i < m; i++) {
s0[i] = max(s0[i - ], tmp + fir[a[i]]);
tmp += eVal[i];
} tmp = 0LL;
for(int i = m; i > ; i--) {
s1[i] = max(s1[i + ], tmp + fir[a[i]]);
tmp += eVal[i - ];
} tmp = 0LL;
for(int i = ; i <= m; i++) {
t0[i] = max(t0[i - ], max(mx[i], tmp + fir[a[i]]));
chkMax(tmp, fir[a[i]]);
tmp += eVal[i];
} tmp = 0LL;
for(int i = m; i > ; i--) {
t1[i] = max(t1[i + ], max(mx[i], tmp + fir[a[i]]));
chkMax(tmp, fir[a[i]]);
tmp += eVal[i - ];
} /* printf("\n");
for(int i = 1; i <= m; i++)
printf("%lld ", s0[i]);
printf("\n"); for(int i = 1; i <= m; i++)
printf("%lld ", s1[i]);
printf("\n"); for(int i = 1; i <= m; i++)
printf("%lld ", t0[i]);
printf("\n"); for(int i = 1; i <= m; i++)
printf("%lld ", t1[i]);
printf("\n"); */ ll ans = t0[m];
for(int i = ; i < m; i++)
chkMin(ans, max(max(t0[i], t1[i + ]), s0[i] + s1[i + ] + eVal[m])); printf("%lld\n", ans);
return ;
}

CF835F Roads in the Kingdom的更多相关文章

  1. [NOI2013]快餐店 / CF835F Roads in the Kingdom (基环树)

    题意 一颗基环树,选一对点使得这两个点的最短距离最大. 题解 相当于找基环树的直径,但是这个直径不是最长链,是基环树上的最短距离. 然后不会做. 然后看了ljh_2000的博客. 然后会了. 这道题最 ...

  2. CF835F Roads in the Kingdom/UOJ126 NOI2013 快餐店 树的直径

    传送门--CF 传送门--UOJ 题目要求基环树删掉环上的一条边得到的树的直径的最小值. 如果直接考虑删哪条边最优似乎不太可做,于是考虑另一种想法:枚举删掉的边并快速地求出当前的直径. 对于环上的点, ...

  3. Codeforces 835 F. Roads in the Kingdom

    \(>Codeforces\space835 F. Roads in the Kingdom<\) 题目大意 : 给你一棵 \(n\) 个点构成的树基环树,你需要删掉一条环边,使其变成一颗 ...

  4. Codeforces 835 F Roads in the Kingdom(树形dp)

    F. Roads in the Kingdom(树形dp) 题意: 给一张n个点n条边的无向带权图 定义不便利度为所有点对最短距离中的最大值 求出删一条边之后,保证图还连通时不便利度的最小值 $n & ...

  5. codeforces 427 div.2 F. Roads in the Kingdom

    F. Roads in the Kingdom time limit per test 2 seconds memory limit per test 256 megabytes input stan ...

  6. Codeforces 835F Roads in the Kingdom (环套树 + DP)

    题目链接 Roads in the Kingdom 题意  给出一个环套树的结构,现在要删去这个结构中的一条边,满足所有点依然连通. 删边之后的这个结构是一棵树,求所有删边情况中树的直径的最小值. 显 ...

  7. 题解-CodeForces835F Roads in the Kingdom

    Problem CodeForces-835F 题意:求基环树删去环上任意一边后直径最小值,直径定义为所有点对最近距离的最大值 Solution 首先明确删去环上一点是不会影响树内直径的,所以应当先把 ...

  8. Codeforces 835F Roads in the Kingdom - 动态规划

    题目传送门 传送点I 传送点II 传送点III 题目大意 给定一颗基环树,要求删去其中一条边,使得剩下的图形是一棵树,并且最长路的长度最短,求最长路的最短长度. 路径可以分为两部分:跨过环 和 在树内 ...

  9. codeforces:Roads in the Kingdom分析和实现

    题目大意:国家有n个城市,还有n条道路,每条道路连通两个不同的城市,n条道路使得所有n个城市相互连通.现在国家经费不足,要关闭一条道路.国家的不便度定义为国家中任意两个不同的城市之间的距离的最大值,那 ...

随机推荐

  1. 给UIButton设置阴影及动画组

    //设置“开启旅程”按钮 UIButton *startBtn = self.startBtn; CGFloat btnW = ; CGFloat btnH = ; CGFloat btnX = (s ...

  2. Weblogic配置SSl使用Https

    一 .可以开启自带的SSL连接 启动weblogic,进入左侧菜单,点击左侧的安全领域-->点击myrealm-->点击角色和策略-->点击服务器AdminServer 点击保存,w ...

  3. Markdown 中的目录自动生成功能 TOC

    目录 Markdown 中的目录自动生成功能 TOC 1. 标题一 1.1 标题二 1.标题二 2. 标题一 2.1 标题二 2.2 标题二 Markdown 中的目录自动生成功能 TOC 1. 标题 ...

  4. PADS Logic 脚本的 Fields 一个对象记录

    PADS Logic 脚本的 Fields 一个对象记录 PADS Laogic 有一个非常棒的脚本功能,可以导出所以元件. 我目前是把脚本绑定到 Ctrl+S 上,在保存时自动导出 txt 文件,方 ...

  5. spring的<array>标签错误

    1,复习了一下spring xml的配置 单个默认命名空间 我们看到,在配置文件中,beans,bean等元素我们是没有使用命名空间前缀的.重复限定一个要在命名空间中使用的元素或属性可能会非常麻烦.这 ...

  6. 程序4-2 access函数实例

    //http://blog.chinaunix.net/uid-24549279-id-71355.html /* ========================================== ...

  7. etcd使用经历

    etcd是一个开源的.分布式的键值对数据存储系统,提供共享配置.服务的注册和发现.etcd与zookeeper相比算是轻量级系统,两者的一致性协议也一样,etcd的raft比zookeeper的pax ...

  8. AngularJS:模型

    ylbtech-AngularJS:模型 1.返回顶部 1. AngularJS ng-model 指令 ng-model 指令用于绑定应用程序数据到 HTML 控制器(input, select, ...

  9. Java中的intern变量的讲解

    一般我们变成很少使用到 intern这个方法,今天我就来解释一下这个方法是干什么的,做什么用的 首先请大家看一个例子: public static void main(String[] args) t ...

  10. python开发IO模型:阻塞&非阻塞&异步IO&多路复用&selectors

    一 IO模型介绍 为了更好地了解IO模型,我们需要事先回顾下:同步.异步.阻塞.非阻塞 同步(synchronous) IO和异步(asynchronous) IO,阻塞(blocking) IO和非 ...