鱼C论坛

 找回密码
 立即注册
查看: 2053|回复: 10

[心之碎片][0622] - 巡逻

[复制链接]
发表于 2024-6-22 19:09:45 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
本帖最后由 柿子饼同学 于 2024-6-22 19:30 编辑
巡逻 link
提交 4 次
3 h

知识点
dp求树的直径 贪心


思路
K == 0, ans0 = 2*(n - 1)
K == 1, 取直径1, ans1 = ans0 - 直径1 + 1
K == 2, 直径上的边权变成 -1, 再算直径2, ans2 = ans1 - 直径2 + 1
这里取反边权是因为, 第二条边如果覆盖了直径, 路程反而会增加这一段的, 别的路径不碍事
求直径就相当于求让路径可以尽可能减小的路程
O(n)


注意点
dfs 不能处理负权树求直径 , 只能用 dp 求, 写的时候 dp 写反了 , 要注意是用 ed 求出 u 的值
证明取直径最优 :
调整法 分两种情况讨论:
一:若选的第一个环与直径无相交的边,则第二个环选直径最优,这等价于第一个环选直径。
二:若选的第一个环与直径有相交的边,将直径与第二个环相交但不与第一个环相交的部分加到第一个环上,答案不变,然后再在第一个环上加上直径上不与第二个环重叠的点,答案增加,因此不如第一个环就直接选直径。
综上,第一个环选直径一定不劣。

代码
  1. #include <bits/stdc++.h>
  2. using namespace std;

  3. const int N = 1e5 + 5;

  4. int n, k, ans;
  5. vector<int> e[N];
  6. int p, q, f[N], d[N];
  7. bitset<N> isd;

  8. void dfs(int u, int pa, int & id){
  9.     for(auto ed : e[u]){
  10.         if(ed == pa) continue;
  11.         f[ed] = u;
  12.         if(isd[u] && isd[ed]) d[ed] = d[u] - 1;
  13.         else d[ed] = d[u] + 1;

  14.         if(d[0] <= d[ed]){
  15.             d[0] = d[ed];
  16.             id = ed;
  17.         }

  18.         dfs(ed, u, id);
  19.     }   
  20. }

  21. void Getd1(){
  22.     d[0] = 0, f[1] = 0, d[1] = 0;
  23.     dfs(1, 0, p);
  24.     d[0] = 0, d[p] = 0, f[p] = 0;
  25.     dfs(p, 0, q);
  26. }

  27. int dp[N], res;
  28. void Getd2(int u, int f){
  29.     for(auto ed : e[u]){
  30.         if(ed == f) continue;
  31.         int w = 1;
  32.         if(isd[ed] && isd[u]) w = -1;
  33.         Getd2(ed, u);
  34.         res = max(res, dp[u] + dp[ed] + w);
  35.         dp[u] = max(dp[u], dp[ed] + w);
  36.     }
  37. }

  38. int main(){
  39.     ios::sync_with_stdio(0);
  40.     cin.tie(0);

  41.     cin >> n >> k;
  42.     for(int i = 1; i < n; i++){
  43.         int x, y;
  44.         cin >> x >> y;
  45.         e[x].emplace_back(y);
  46.         e[y].emplace_back(x);
  47.     }

  48.     ans = 2*(n - 1);
  49.     if(k == 0){
  50.         cout << ans;
  51.         return 0;
  52.     }

  53.     Getd1();   
  54.     ans -= d[0] - 1;
  55.     if(k == 1){
  56.         cout << ans;
  57.         return 0;
  58.     }

  59.     for(int i = q; i; i = f[i]){
  60.         isd[i] = 1;
  61.     }
  62.     Getd2(1, 0);
  63.     ans -= res - 1;
  64.     cout << ans;

  65.     return 0;
  66. }
复制代码



本帖被以下淘专辑推荐:

小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

头像被屏蔽
发表于 2024-6-26 20:34:42 | 显示全部楼层

回帖奖励 +1 鱼币

提示: 作者被禁止或删除 内容自动屏蔽
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

头像被屏蔽
发表于 2024-6-26 20:34:55 | 显示全部楼层

回帖奖励 +1 鱼币

提示: 作者被禁止或删除 内容自动屏蔽
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

头像被屏蔽
发表于 2024-6-26 20:35:08 | 显示全部楼层

回帖奖励 +1 鱼币

提示: 作者被禁止或删除 内容自动屏蔽
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

头像被屏蔽
发表于 2024-6-26 20:35:19 | 显示全部楼层

回帖奖励 +1 鱼币

提示: 作者被禁止或删除 内容自动屏蔽
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

头像被屏蔽
发表于 2024-6-26 20:35:29 | 显示全部楼层

回帖奖励 +1 鱼币

提示: 作者被禁止或删除 内容自动屏蔽
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

头像被屏蔽
发表于 2024-6-26 20:35:39 | 显示全部楼层

回帖奖励 +1 鱼币

提示: 作者被禁止或删除 内容自动屏蔽
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

头像被屏蔽
发表于 2024-6-26 20:35:52 | 显示全部楼层

回帖奖励 +1 鱼币

提示: 作者被禁止或删除 内容自动屏蔽
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

头像被屏蔽
发表于 2024-6-26 20:36:05 | 显示全部楼层

回帖奖励 +1 鱼币

提示: 作者被禁止或删除 内容自动屏蔽
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

头像被屏蔽
发表于 2024-6-26 20:36:22 | 显示全部楼层

回帖奖励 +1 鱼币

提示: 作者被禁止或删除 内容自动屏蔽
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2024-7-2 18:31:58 | 显示全部楼层

回帖奖励 +1 鱼币

小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2025-4-27 17:06

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表