首页 > 其他分享 >P8119 「Wdoi-1.5」幻想乡游览计划

P8119 「Wdoi-1.5」幻想乡游览计划

时间:2024-11-16 21:56:53浏览次数:1  
标签:1.5 P8119 emplace int Wdoi back vis ans push

不妨考虑树的情况,对于图只要取一棵生成树即可。

\(k\le 4n\) 是容易的,两个点分别 dfs 就是 \(\le 4n\) 次。

对于 \(k\le 3n\),考虑一个做法:一个人去遍历整棵树,每次拓展新点时交换。不难证明正确性,次数 \(\le 3n\)。

考虑优化这个策略。注意到其中一个点一直在根,这非常浪费。事实上我们可以两个点同时递归两棵子树,每次同时走到一个新点然后交换。

但是这个优化在两棵子树大小差距过大时用处不大,考虑取重心,每个子树划分给某个人去遍历。假设分给两人的大小之和分别为 \(S_1\) 和 \(S_2\),那么总次数就是 \(2\times(S_1+S_2)+\max(S_1,S_2)\)。

考虑从大往小考虑每棵子树,每次划分给较小的 \(S\),可以证明 \(\max S\le \dfrac{2}{3}n\),总次数 \(\le\dfrac{8}{3} n\)。

code
#include <bits/stdc++.h>
#define ALL(x) begin(x), end(x)
using namespace std;
void file() {
  freopen("1.in", "r", stdin);
  freopen("1.out", "w", stdout);
}
using ll = long long;

const int kL = 5e5 + 5;
int n, m;
array<int, kL> siz;
array<bool, kL> vis;
array<vector<int>, kL> g;
string A = "Ran", B = "Chen";

struct DSU {
  array<int, kL> fa;
  DSU() { iota(ALL(fa), 0); }
  int find(int x) {
    return (fa[x] == x) ? x : (fa[x] = find(fa[x]));
  }
  void merge(int x, int y) { fa[find(x)] = find(y); }
}dsu;

int findrt(int x, int Fa) {
  int mx = 0, rt = 0; siz[x] = 1;
  for(int to : g[x]) {
    if(to == Fa) continue;
    if(int tmp = findrt(to, x))
      rt = tmp;
    siz[x] += siz[to];
    mx = max(mx, siz[to]);
  }
  mx = max(mx, n - siz[x]);
  return (mx * 2 <= n) ? x : rt;
}

void dfs(int x, int Fa) {
  if(Fa) g[x].erase(find(ALL(g[x]), Fa));
  for(int to : g[x]) dfs(to, x);
}

vector<pair<string, int>> ans;

void push(int x, vector<int>& buc) {
  buc.push_back(x);
  for(int to : g[x]) {
    push(to, buc);
    buc.push_back(x);
  }
}

vector<int> vx, vy;

void solve(int x, int Fa) {
  if(g[x].empty()) return ;
  sort(ALL(g[x]), [&](int a, int b) { return siz[a] > siz[b]; });
  for(int to : g[x]) {
    vector<int> buc;
    push(to, buc);
    buc.push_back(x);
    if(vx.size() < vy.size()) {
      for(int i : buc) vx.push_back(i);
    }else {
      for(int i : buc) vy.push_back(i);
    }
  }
}

void getans() {
  int i, j;
  for(i = j = 0; (i < vx.size()) && (j < vy.size()); ) {
    int a = vx[i], b = vy[j];
    if(vis[a]) { ans.emplace_back(A, a); i++; }
    if(vis[b]) { ans.emplace_back(B, b); j++; }
    if(!vis[a] && !vis[b]) {
      i++, j++, vis[a] = vis[b] = 1;
      ans.emplace_back(A, a);
      ans.emplace_back(B, b);
      ans.emplace_back("Swap", -1), swap(A, B);
    }
  }
  for(; i < vx.size(); i++) {
    int p = vx[i];
    if(vis[p]) ans.emplace_back(A, p);
    else {
      vis[p] = 1;
      ans.emplace_back(A, p);
      ans.emplace_back("Swap", -1), swap(A, B);
    }
  }
  for(; j < vy.size(); j++) {
    int p = vy[j];
    if(vis[p]) ans.emplace_back(B, p);
    else {
      vis[p] = 1;
      ans.emplace_back(B, p);
      ans.emplace_back("Swap", -1), swap(A, B);
    }
  }
}

int main() {
  // file();
  ios::sync_with_stdio(0), cin.tie(0);
  cin >> n >> m;
  for(int i = 1, u, v; i <= m; i++) {
    cin >> u >> v;
    if(dsu.find(u) != dsu.find(v)) {
      dsu.merge(u, v);
      g[u].push_back(v);
      g[v].push_back(u);
    }
  }
  ans.reserve(3 * n);
  vx.reserve(2 * n);
  vy.reserve(2 * n);
  int root = findrt(1, 0);
  assert(findrt(root, 0) == root);
  dfs(root, 0), solve(root, 0), getans();
  cout << root << " ";
  cout << ans.size() << "\n";
  for(auto k : ans) {
    if(~k.second) cout << k.first << " " << k.second << "\n";
    else cout << k.first << "\n";
  }
  return 0;
}

标签:1.5,P8119,emplace,int,Wdoi,back,vis,ans,push
From: https://www.cnblogs.com/cjoierzdc/p/18549900

相关文章

  • 题解:P7836 「Wdoi-3」夜雀 collecting
    题解摘自做题记录。分析数据范围明显得要让我们分开搞。【Sub2】应该是暴力。这里有个主体思路,我们完全可以贪心地将当前背包里的食材删掉,直到每种出现过的食材数量刚好为\(1\)。因为我们保留更多的是没有用的。那么我们就可以用二进制数表示\(x\)种食材的出现状态了。同......
  • 11.5
    实验8:适配器模式本次实验属于模仿型实验,通过本次实验学生将掌握以下内容:1、理解适配器模式的动机,掌握该模式的结构;2、能够利用适配器模式解决实际问题。 [实验任务一]:双向适配器实现一个双向适配器,使得猫可以学狗叫,狗可以学猫抓老鼠。实验要求:  1、Cat.javapackag......
  • Qwen1.5大语言模型微调实践
    在人工智能领域,大语言模型(LargeLanguageModel,LLM)的兴起和广泛应用,为自然语言处理(NLP)带来了前所未有的变革。Qwen1.5大语言模型作为其中的佼佼者,不仅拥有强大的语言生成和理解能力,而且能够通过微调(fine-tuning)来适应各种特定场景和任务。本文将带领大家深入实战,探索如何对Q......
  • 空调小1.5匹和1.5匹查看
    空调的小1.5匹和1.5匹主要通过以下几种方式来区分:1.**查看制冷量**:-小1.5匹空调的制冷量通常为3200W左右。-标准1.5匹空调的制冷量大约为3500W。2.**检查适用面积**:-小1.5匹空调适合用于15-18平方米左右的房间。-标准1.5匹空调适合用于18-22平方米左右的空间......
  • 「ComfyUI」增强图像细节只需要一个节点,SD1.5、SDXL、FLUX.1 全支持,简单好用!
    ‍‍‍‍‍前言今天给小伙伴们介绍一个非常简单,但又相当好使的一个插件。功能很简单,就是增加或者减少图像的细节,节点也很简单,就一个节点,只需要嵌入我们的ComfyUI的基础工作流中就可以了,随插随用。而且该插件不仅支持SD1.5和SDXL,甚至最新出的FLUX.1模型也是支持的......
  • VMware Tanzu CLI 1.5.0 - VMware Kubernetes 发新版的命令行工具
    VMwareTanzuCLI1.5.0-VMwareKubernetes发新版的命令行工具VMware构建、签名和支持的开源Kubernetes容器编排平台的完整分发版请访问原文链接:https://sysin.org/blog/vmware-tanzu-cli/查看最新版。原创作品,转载请保留出处。作者主页:sysin.orgVMwareTanzu命令行......
  • 2024.11.5人工智能学记6
    人工智能(ArtificialIntelligence),引文缩写为AI。它是研究、开发用于模拟、延伸和扩展人的智能的理论、方法、技术及应用系统的一门新的技术科学。(一)学科范畴人工智能是一门边沿学科,属于自然科学、社会科学、技术科学三向交叉学科。(二)涉及学科与领域哲学和认知科学,数学,神经生......
  • 1.5--1792:迷宫
    迷宫题目传送门思路:迷宫必须用深搜(我是深搜党)递归出口条件:if(ha==hb&&la==lb) { cout<<"YES"<<endl; flag=1;}//判断是否是终点判断越界if(dx>=0&&dx<n&&dy>=0&&dy<n&&s[dx][dy]=='.')主函数:i......
  • 【2024潇湘夜雨】WIN11_Pro-Workstation_24H2.26120.2213软件选装纯净特别版11.5
    【系统简介】=============================================================1.本次更新母盘来自WIN11_Pro-Workstation_24H2.26120.2213.进桌面后稍等片刻,等待后续部分优化完成。2.全程离线精简、无人值守调用优化处理制作。部分优化适配系统可能要重启几次,即使显示适配失败也不......
  • 11.5 非递归的归并排序
    #include<bits/stdc++.h>usingnamespacestd;#defineintlonglongintn;inthelp[1008611];intarr[1008611];voidmerge(intl,intm,intr){inti=l;inta=l;intb=m+1;while(a<=m&&b<=r){help[i++]=arr[a]......