题目链接  CCPC2016 Changchun Problem E

题意  给定一个$n$个点$n$条边的无向图,现在从某一点$s$出发,每个点都经过一遍,最后在$t$点停止,经过的边数为$l$

    求字典序最小的三元组$(l, s, t)$

设环的长度为$c$,

当$s$和$t$在同一棵子树上的时候,$s$到$t$的路径上的边和环上的边只要走一次,其他边都要走两次,那么答案为$2n - c - len$

$len$为$s$到$t$的路径的长度;

当$s$和$t$不在同一棵子树上的时候,设$s$走到环上的第一个点为$u$,$t$走到环的第一个点为$v$。

那么这个时候考虑每条边走过的次数。

对于不在环上的边,从$s$到$u$,从$v$到$t$的路径只要走一次,其余的边都要走两次。

对于在环上的边,从$u$到$v$的路径只要走一次,其余的部分都要走两次,但是有一条边不用经过(一次都不用走)

那么答案为$2n - 2 - len(s, u) - len(u, v) - len(v, t)$;

对于第一种情况,我们对环上每棵树都求一条字典序最小的直径然后更新答案即可。

对于第二种情况,我们需要最大化$len(s, u) + len(u, v) + len(v, t)$的值。

考虑每个环上的点,显然$s$和$t$的最佳选择都是从这个点往里走可以走到的最深的点。

设环上的点依次排列为:$a_{1}, a_{2}, a_{3}, ......, a_{cnt}$。

设每个环上的点往子树方向走能走到的最深的深度为$c_{1}, c_{2}, c_{3}, ......, c_{cnt}$

倍长a数组和c数组,对于每个位置$i(cnt < i <= 2 * cnt)$,找到一个最佳的点$j(i - cnt + 1 <= j <= i - 1)$。

使得$i - j + c[j] + c[i] = i + c[i] + (c[j] - j)$的值最大。

那么用单调队列维护$c[j] - j$的最大值即可。我为了方便偷懒用了ST表。

#include <bits/stdc++.h>

using namespace std;

#define	rep(i, a, b)	for (int i(a); i <= (b); ++i)
#define dec(i, a, b) for (int i(a); i >= (b); --i)
#define fi first
#define se second
#define MP make_pair typedef long long LL;
typedef pair <int, int> PII; const int N = 1e5 + 10; struct node{
int x, y;
} b[N << 1]; node f[N << 1][20]; int T;
int n, cnt;
int a[N], isroot[N], father[N], vis[N];
int len, l, r;
int lg[N << 1];
int m;
int ca = 0;
vector <int> v[N];
pair <int, PII> ans;
PII c[N]; int get_circle(int x){
vis[x] = 1;
for (auto u : v[x]){
if (u == father[x]) continue;
father[u] = x;
if (vis[u]){
cnt = 0;
int w = x;
while (w ^ u){
a[++cnt] = w;
isroot[w] = cnt;
w = father[w];
} a[++cnt] = u;
isroot[u] = cnt;
return 1;
}
if (get_circle(u)) return 1;
} return 0;
} inline node mx(const node &a, const node &b){
if (a.x == b.x){
if (a.y < b.y) return a;
else return b;
} if (a.x > b.x) return a; else return b;
} void dfs(int x, int fa, int dep){
if ((dep > len) || (dep == len && x < l)){
len = dep;
l = x;
} for (auto u : v[x]){
if (u == fa || isroot[u]) continue;
dfs(u, x, dep + 1);
}
} void dfs2(int x, int fa, int dep, int extra){
if ((dep > len) || (dep == len && x < r)){
len = dep;
r = x;
} for (auto u : v[x]) if ((u != fa) && (!isroot[u] || u == extra)){
dfs2(u, x, dep + 1, extra);
}
} inline node solve(int l, int r){
int k = lg[r - l + 1];
return mx(f[l][k], f[r - (1 << k) + 1][k]);
} int main(){ lg[1] = 0;
rep(i, 2, 2e5) lg[i] = lg[i >> 1] + 1; scanf("%d", &T);
while (T--){
scanf("%d", &n);
if (n == 2) while (1);
rep(i, 0, n + 1){
v[i].clear();
isroot[i] = 0;
father[i] = 0;
vis[i] = 0;
} cnt = 0;
rep(i, 1, n){
int x, y;
scanf("%d%d", &x, &y);
v[x].push_back(y);
v[y].push_back(x);
} father[1] = 0;
get_circle(1); memset(c, -1, sizeof c);
ans = MP(1e9, MP(-1, -1));
rep(i, 1, cnt){
len = -1;
l = -1;
r = -1;
dfs(a[i], 0, 0); c[i] = MP(len, l);
len = -1;
dfs2(l, 0, 0, a[i]);
if (l > r) swap(l, r);
ans = min(ans, MP(2 * n - len - cnt, MP(l, r)));
} rep(i, 1, cnt){
b[i] = {c[i].fi - i + 1, c[i].se};
b[i + cnt] = {c[i].fi - (i - 1 + cnt), c[i].se};
} m = cnt << 1;
memset(f, 0, sizeof f); rep(i, 1, m) f[i][0] = b[i];
rep(j, 1, 18){
rep(i, 1, m){
if ((i + (1 << j) - 1) <= m) f[i][j] = mx(f[i][j - 1], f[i + (1 << (j - 1))][j - 1]);
}
} rep(i, cnt + 1, m){
node now = solve(i - cnt + 1, i - 1);
int ll = now.y, rr = c[i - cnt].se;
if (ll > rr) swap(ll, rr);
int ret = c[i - cnt].fi + i - 1 + (now.x);
ans = min(ans, MP(2 * n - 2 - ret , MP(ll, rr) ) );
}
printf("Case #%d: %d %d %d\n", ++ca, ans.fi, ans.se.fi, ans.se.se);
} return 0; }

HDU 5915 The Fastest Runner Ms. Zhang (CCPC2016 长春 E题,分类讨论 + 求字典序最小的直径 + 数据结构寻找最小值)的更多相关文章

  1. HDU 4423 Simple Function(数学题,2012长春D题)

    Simple Function Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)T ...

  2. hdu 2191 珍惜现在,感恩生活 多重背包入门题

    背包九讲下载CSDN 背包九讲内容 多重背包: hdu 2191 珍惜现在,感恩生活 多重背包入门题 使用将多重背包转化为完全背包与01背包求解: 对于w*num>= V这时就是完全背包,完全背 ...

  3. HDU 2080 夹角有多大II (数学) atan(y/x)分类求角度

    夹角有多大II Problem Description 这次xhd面临的问题是这样的:在一个平面内有两个点,求两个点分别和原点的连线的夹角的大小.注:夹角的范围[0,180],两个点不会在圆心出现. ...

  4. HDU 5203 Rikka with wood sticks 分类讨论

    题目链接: hdu:http://acm.hdu.edu.cn/showproblem.php?pid=5203 bc(chinese):http://bestcoder.hdu.edu.cn/con ...

  5. HDU 1533:Going Home(KM算法求二分图最小权匹配)

    http://acm.hdu.edu.cn/showproblem.php?pid=1533 Going Home Problem Description   On a grid map there ...

  6. HDU 6627 equation (分类讨论)

    2019 杭电多校 5 1004 题目链接:HDU 6627 比赛链接:2019 Multi-University Training Contest 5 Problem Description You ...

  7. HDU 6665 Calabash and Landlord (分类讨论)

    2019 杭电多校 8 1009 题目链接:HDU 6665 比赛链接:2019 Multi-University Training Contest 8 Problem Description Cal ...

  8. hdu 1465:不容易系列之一(递推入门题)

    不容易系列之一 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Sub ...

  9. HDU 2504 又见GCD(最大公约数与最小公倍数变形题)

    又见GCD Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Subm ...

随机推荐

  1. 机器学习框架Tensorflow数字识别MNIST

    SoftMax回归  http://ufldl.stanford.edu/wiki/index.php/Softmax%E5%9B%9E%E5%BD%92 我们的训练集由  个已标记的样本构成: ,其 ...

  2. ThreadLocal 学习

    JDK 1.2版本就已经提供了java.lang.ThreadLocal.其为多线程程序的并发问题提供了一种新的思路.使用该工具类可以简洁地编写出优美的多线程程序. 当使用ThreadLocal维护变 ...

  3. RGB和YUV、YCbCr 以及格式的转换总结

    比较好的文章收集链接: https://www.douban.com/note/76361504/ http://blog.sina.com.cn/s/blog_a85e142101010h8n.ht ...

  4. 201621123034 《Java程序设计》第10周学习总结

    作业10-异常 1. 本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结异常相关内容. 2. 书面作业 本次PTA作业题集异常 1. 常用异常 结合题集题目7-1回答 1.1 自己以前编写 ...

  5. 清除浮动float (:after方法)

    1. 什么时候需要清除浮动?清除浮动有哪些方法? (1)对元素进行了浮动(float)后,该元素就会脱离文档流,浮动在文档之上.在CSS中,任何元素都可以浮动.浮动元素会生成一个块级框,而不论它本身是 ...

  6. 【BZOJ1179】[Apio2009]Atm (tarjan+SPFA)

    显而易见的tarjan+spfa...不解释了 ; type edgetype=record toward,next:longint; end; var edge1,edge2:..maxn] of ...

  7. POJ 3974 Palindrome | 马拉车模板

    给一个字符串,求最长回文字串有多长 #include<cstdio> #include<algorithm> #include<cstring> #define N ...

  8. BZOJ1483 [HNOI2009]梦幻布丁 【链表 + 启发式合并】

    题目 N个布丁摆成一行,进行M次操作.每次将某个颜色的布丁全部变成另一种颜色的,然后再询问当前一共有多少段颜色. 例如颜色分别为1,2,2,1的四个布丁一共有3段颜色. 输入格式 第一行给出N,M表示 ...

  9. Build RPM package from source code

    # yum install rpm-build# wget http://rsync.samba.org/ftp/rsync/rsync-3.0.9.tar.gz# vim rsync.specNam ...

  10. Linux 软连接 & 硬链接

    1.Linux链接概念Linux链接分两种,一种被称为硬链接(Hard Link),另一种被称为符号链接(Symbolic Link).默认情况下,ln命令产生硬链接. [硬连接]硬连接指通过索引节点 ...