CF1179D Fedor Runs for President
CF1179D Fedor Runs for President
题意
给一棵
n
个点的树,求加入一条边后,最多有多少条无向简单路径简单路径定义为任意一个点最多经过一次的路径
思路
- 我们若将
i
和j
相连,我们可以将i
到j
的路径拉直- 路径上每个点有一个以该点为根的子树,记子树大小为
size[i]
- 该路径上不同子树之间的点相互访问的简单路径增加了一条
- 增加路径数 ∑ ( n − s i z e [ i ] ) ∗ s i z e [ i ] = 1 2 ( n 2 − ∑ s i z e [ i ] 2 ) \sum {(n-size[i])*size[i]} = \frac{1}{2} (n^2- \sum size[i]^2) ∑(n−size[i])∗size[i]=21(n2−∑size[i]2),
i
为路径上的点 - 综上,我们要求的就是 ∑ s i z e [ i ] \sum size[i] ∑size[i]的最小值
- 路径上每个点有一个以该点为根的子树,记子树大小为
- 然后我们发现一个规律:路径的两端必定为叶子或者根
- 若不为叶子,我可以让他的端点向子树方向扩展,那么得到
size[i]
更小( n 2 > x 2 + ( n − x ) 2 n^2>x^2+(n-x)^2 n2>x2+(n−x)2)
- 若不为叶子,我可以让他的端点向子树方向扩展,那么得到
- 令
dp[i]
为以i
为根的子树中 ∑ s i z e [ i ] \sum size[i] ∑size[i]最小的链- 转移方程为 d p [ i ] = m i n ( d p [ j ] + ( s i z e [ i ] − s i z e [ j ] ) 2 ) dp[i]=min(dp[j]+(size[i]-size[j])^2) dp[i]=min(dp[j]+(size[i]−size[j])2)
n_size[now] = 1;
for (auto it : E[now])
{if (it == fa)continue;dfs(it, now);n_size[now] += n_size[it];
}
dp[now] = n_size[now] * n_size[now];
for (auto it : E[now])
{if (it == fa)continue;dp[now] = min(dp[now], dp[it] + (n_size[now] - n_size[it]) * (n_size[now] - n_size[it]));
}
- 对于根
s
,可以将i
,j
和并- a n s = m i n ( a n s , d p [ i ] + d p [ j ] + ( n − s i z e [ i ] − s i z e [ j ] ) 2 ) ans=min(ans,dp[i]+dp[j]+(n-size[i]-size[j])^2) ans=min(ans,dp[i]+dp[j]+(n−size[i]−size[j])2)
- 可以将
s
与i
合并, a n s = m i n ( d p [ i ] + ( n − s i z e [ i ] ) 2 ) ans=min(dp[i]+(n-size[i])^2) ans=min(dp[i]+(n−size[i])2)
- 对上面 n 2 n^2 n2做法显然会
t
,我们尝试斜率优化- a n s = d p [ i ] + d p [ j ] + ( n − s i z e [ i ] − s i z e [ j ] ) 2 ans = dp[i] + dp[j] + (n - size[i] - size[j]) ^ 2 ans=dp[i]+dp[j]+(n−size[i]−size[j])2
- d p [ j ] + ( n − s i z e [ j ] ) 2 = 2 ∗ s i z e [ i ] ∗ ( n − s i z e [ j ] ) + a n s − s i z e [ i ] 2 − d p [ i ] dp[j] + (n - size[j]) ^ 2 = 2 * size[i] * (n - size[j]) + ans - size[i] ^ 2 - dp[i] dp[j]+(n−size[j])2=2∗size[i]∗(n−size[j])+ans−size[i]2−dp[i]
x: n-size[j]
- y : d p [ j ] + ( n − s i z e [ j ] ) 2 y: dp[j] +(n-size[j])^2 y:dp[j]+(n−size[j])2
k: 2*size[i]
- b : a n s − s i z e [ i ] 2 − d p [ i ] b: ans- size[i] ^2 - dp[i] b:ans−size[i]2−dp[i]
register LL x, y, k, b;
q[top = 1] = make_pair(n - s[1].first, s[1].second + (n - s[1].first) * (n - s[1].first));
for (int i = 2; i <= tot; i++)
{x = n - s[i].first;y = s[i].second + x * x;k = 2 * s[i].first;int pos = binary_search(k);b = q[pos].second - k * q[pos].first;ans = min(ans, b + s[i].first * s[i].first + s[i].second);//(y2-y1)/(x2-x1) >= (y3-y1)/(x3-x1)while (top > 1 && (q[top].second - q[top - 1].second) * (x - q[top - 1].first) >= (y - q[top - 1].second) * (q[top].first - q[top - 1].first))top--;q[++top] = make_pair(x, y);
}
ans = min(ans, dp[now] + (n - n_size[now]) * (n - n_size[now]));
a[now] = make_pair(n_size[now], dp[now]);
代码
#include <bits/stdc++.h>
using namespace std;
const int maxn = 5e5 + 5;
typedef long long LL;
LL n;
vector<int> E[maxn];
LL n_size[maxn], dp[maxn];
//dp表示以 i 为根的子数,连接叶子节点 子树平方和最小的路径
typedef pair<LL, LL> pll;
bool cmp(pll& a, pll& b)
{return a.first > b.first;
}
pll a[maxn], s[maxn], q[maxn];
int top;
LL binary_search(LL k)
{if (top == 1)return 1;int l = 2, r = top, mid, ans = 1;while (l <= r) {mid = (l + r) >> 1;if ((q[mid].second - q[mid - 1].second) <= k * (q[mid].first - q[mid - 1].first))ans = max(ans, mid),l = mid + 1;elser = mid - 1;}return ans;
}
LL ans = 1e18;
void dfs(int now, int fa)
{n_size[now] = 1;for (auto it : E[now]) {if (it == fa)continue;dfs(it, now);n_size[now] += n_size[it];}dp[now] = n_size[now] * n_size[now];for (auto it : E[now]) {if (it == fa)continue;dp[now] = min(dp[now], dp[it] + (n_size[now] - n_size[it]) * (n_size[now] - n_size[it]));}// ans = dp[i] + dp[j] + (n - size[i] - size[j]) ^ 2// dp[j] + (n - size[j]) ^ 2 = 2 * size[i] * (n - size[j]) + ans - size[i] ^ 2 - dp[i]int tot = 0;for (auto it : E[now]) {if (it == fa)continue;s[++tot] = a[it];}// x: n-size[j]// y: dp[j] +(n-size[j])^2// k: 2*size[i]// b: ans- size[i] ^2 - dp[i]sort(s + 1, s + 1 + tot, cmp);int l = 1, r = 1;register LL x, y, k, b;q[top = 1] = make_pair(n - s[1].first, s[1].second + (n - s[1].first) * (n - s[1].first));for (int i = 2; i <= tot; i++) {x = n - s[i].first;y = s[i].second + x * x;k = 2 * s[i].first;int pos = binary_search(k);b = q[pos].second - k * q[pos].first;ans = min(ans, b + s[i].first * s[i].first + s[i].second);//(y2-y1)/(x2-x1) >= (y3-y1)/(x3-x1)while (top > 1 && (q[top].second - q[top - 1].second) * (x - q[top - 1].first) >= (y - q[top - 1].second) * (q[top].first - q[top - 1].first))top--;q[++top] = make_pair(x, y);}ans = min(ans, dp[now] + (n - n_size[now]) * (n - n_size[now]));a[now] = make_pair(n_size[now], dp[now]);
}
int main()
{// freopen("out.txt", "r", stdin);scanf("%I64d", &n);int u, v;for (int i = 1; i < n; i++) {scanf("%d%d", &u, &v);E[u].push_back(v);E[v].push_back(u);}dfs(1, 0);//cout << ans << '\n';printf("%I64d\n", n * (n - 1) / 2 + (n * n - ans) / 2);return 0;
}
CF1179D Fedor Runs for President相关推荐
- Codeforces 1179 D - Fedor Runs for President
D - Fedor Runs for President 思路: 推出斜率优化公式后,会发现最优点只可能来自凸斜率中的第一个元素和最后一个元素, 这两个元素不用维护凸斜率也能知道,就是第一个和上一个元 ...
- Codeforces 1179D Fedor Runs for President [DP,斜率优化]
Codeforces 思路 考虑把连的那两个点中间的链提出来,那么就会变成一条链,链上的每个点挂着一棵子树的形式. 设那些子树的大小为\(S_1,S2,\cdots\),那么新加的简单路径个数就是 \ ...
- CF-567F(President and Roads) DAG必经边
CF-567F(President and Roads) 题目链接 题意 S−>ES->ES−>E的DAGDAGDAG中求: DAGDAGDAG中必经边输出"YESYESY ...
- 2019.11.2图论专题(AtCoder Splatter Painting、President and Roads、Shortest Cycle、ISlands II)
D:AtCoder Grand Contest 012 Splatter Painting 题目描述 Squid喜欢在图中为一些顶点染色(毕竟是鱿鱼 ) 现在有一张由 N 个顶点和 M 条边组成的简单 ...
- How Apache Zeppelin runs a paragraph
转发一篇zeppelin的主力committer Jongyoul Lee的讲解zeppelin的paragraph的运行机制的文章,原文地址:https://medium.com/apache-ze ...
- vivado [Runs 36-335] DCP is not a valid design checkpoint问题解决方法
(1)问题描述 有时候vivado会莫名的出现一下错误: [Runs 36-335] 'xxx.dcp' is not a valid design checkpoint 在遇到这个错误的时候大家不要 ...
- 20100304-001-美国总统The President of the United States of America
美国总统(The President of the United States of America) 美国宪法 1789年4月30日,乔治·华盛顿 1793年3月4日,乔治·华盛顿 1797年3月4 ...
- Vivado报错:[Runs 36-527] DCP does not exist
Vivado报错:[Runs 36-527] DCP does not exist 问题描述:综合工程时,某个IP文件被标红,出现[Runs 36-527] DCP does not exist. ...
- 转载 GIS的下个十年(Peter Batty, president, Spatial Networking)
GIS的下个十年(Peter Batty, president, Spatial Networking) 2008年12月14日 星期日 20:16 转载自:http://hi.baidu.com/l ...
最新文章
- Apache 反向代理,Laravel获取用户真实IP
- 我眼中的计算机,我眼中的计算机-计算机开机背后的故事
- 文献学习(part78-B)--A Survey of Clustering Algorithms for Big Data: T axonomy Empirical Analysis
- HDU2546_用01背包做
- 理解SQL【转http://blog.jobbole.com/55086/】
- WiFi(网络)调试Android手机
- 日志时间与系统时间不一致问题解决方法
- git个人常用的命令
- 2013Esri全球用户大会QA之ArcGIS未来发展
- 【深度相机系列二】深度相机原理揭秘--飞行时间(TOF)
- Springer-Verlag免费下载图书400本
- 公众号第三方平台开发 教程一 创建公众号第三方平台
- C#-进击Hangfire
- WIN 7系统建立无线热点
- .Net Core 3.0 控制台 WebAPI 开发 基础环境搭建.
- 五大列级庄_详解五大名庄背后的1855分级
- python中文版下载安装教程,python最新版本安装教程
- 编程之类的文案_有哪些让人眼前一亮的广告文案?
- cad在线转换_CAD批量转PDF?分享两种方法,一分钟完成所有图纸转换!
- 宁波远洋上交所上市:市值155亿 上半年营收23亿净利4亿
热门文章
- 在html中使用fontIcon 的图标
- 这才是互联网赚钱的正确姿势!你学会了吗?
- 免杀方法(三)msf加载器免杀
- 江苏二本计算机科学与技术好的学校排名,江苏最好的二本学校,2021年江苏二本学校排名前十名单公布...
- gm怎么刷东西 rust_决战常用GM刷物品命令
- HTML的body元素
- 安装 SASS 失败,提示‘mkmf.rb can't find header files for ruby at /usr/share/include/ruby.h’
- checkbox的点击事件
- 英语流利说 第31天
- office中word使用过程中字体排版