首页 > 其他分享 >CF1361E James and the Chase 题解

CF1361E James and the Chase 题解

时间:2024-04-08 19:56:25浏览次数:15  
标签:int 题解 CF1361E 好点 kMaxN ins leq James sum

Description

给定一个有 \(n\) 个点 \(m\) 条边的有向强连通图。称一个点是好的当且仅当它到其他点都有且只有一条简单路径。如果好的点至少有 \(20\%\) 则输出所有好的点,否则输出 -1

单个测试点内有多组数据。
\(1\leq T\leq 2\times 10^3,1\leq n\leq 10^5,1\leq m\leq 2\times 10^5,\sum n\leq 10^5,\sum m\leq 2\times 10^5\)。

Solution

考虑如何判断一个点是否是好的。

先以一个点 \(x\) 为根建出 dfs 树,如果建不出来显然不合法,并且如果一条非树边不是返祖边,就说明存在横叉边,显然不合法。

容易发现满足上面的两个条件就一定合法,但是这样做单次是 \(O(n)\) 的,过不了。

先不妨假设 \(x\) 是好点,那么对于一个点 \(y\),如果他是好点,就说明其子树里有且仅有 \(1\) 条返祖边其祖先为 \(y\) 的祖先,设其为 \(z\to w\)。

然后有一个性质:如果 \(y\) 是好点当且仅当 \(w\) 是好点。

证明:

如果 \(y\) 是好点,由于 \(w\to y\) 只有一条路径,所以 \(w\to y\) 的子树的路径都有且仅有一条,并且 \(y\) 要出 \(w\) 的子树就必须经过 \(w\),由于 \(y\to w\) 子树外的点的路径都是唯一的,所以 \(w\to w\) 子树外的点的路径也是唯一的,所以 \(w\) 是好点。

如果 \(w\) 是好点,由于 \(w\) 到所有点路径唯一且 \(y\) 出 \(w\) 子树必须经过 \(w\),所以 \(y\) 也是好点。

所以先找到一个为好点的 \(x\),然后做树上差分对于每个 \(y\) 求出 \(w\) 用并查集合并即可。

然后对于每个好点就一定和 \(x\) 在同一并查集,否则无论如何也到不了 \(x\)。

至于找 \(x\),就每次随机一个点做 \(100\) 次,失败的概率是 \(\left(\frac{4}{5}\right)^{100}\),非常小。

时间复杂度:\(O\left(100(n+m)\right)\)。

Code

#include <bits/stdc++.h>

// #define int int64_t

const int kMaxN = 1e5 + 5;

int n, m, fl = 1;
int cnt[kMaxN], sum[kMaxN], fa[kMaxN];
bool ins[kMaxN], vis[kMaxN];
std::vector<int> G[kMaxN];

int find(int x) { return x == fa[x] ? x : fa[x] = find(fa[x]); }

void unionn(int x, int y) {
  int fx = find(x), fy = find(y);
  if (fx != fy) fa[fx] = fy;
}

void dfs1(int u) {
  vis[u] = ins[u] = 1;
  for (auto v : G[u]) {
    if (!vis[v]) {
      dfs1(v);
    } else {
      if (!ins[v]) fl = 0;
      else ++cnt[u], --cnt[v], sum[u] += v, sum[v] -= v;
    }
  }
  ins[u] = 0;
}

void dfs2(int u) {
  ins[u] = 1;
  for (auto v : G[u]) {
    if (!ins[v]) {
      dfs2(v);
      cnt[u] += cnt[v], sum[u] += sum[v];
    } else {
    }
  }
  ins[u] = 0;
}

void dickdreamer() {
  std::cin >> n >> m;
  for (int i = 1; i <= n; ++i) G[i].clear();
  for (int i = 1; i <= m; ++i) {
    int u, v;
    std::cin >> u >> v;
    G[u].emplace_back(v);
  }
  std::vector<int> vec;
  for (int i = 1; i <= n; ++i) vec.emplace_back(i);
  std::shuffle(vec.begin(), vec.end(), std::mt19937(std::chrono::steady_clock::now().time_since_epoch().count()));
  for (int i = 0; i < std::min(100, (int)vec.size()); ++i) {
    int x = vec[i];
    for (int i = 1; i <= n; ++i) {
      fa[i] = i;
      cnt[i] = sum[i] = ins[i] = vis[i] = 0;
    }
    fl = 1, dfs1(x);
    if (!fl) continue;
    std::fill_n(ins + 1, n, 0);
    dfs2(x);
    for (int i = 1; i <= n; ++i) {
      if (cnt[i] == 1) {
        unionn(i, sum[i]);
      }
    }
    std::vector<int> idx;
    for (int i = 1; i <= n; ++i)
      if (find(i) == find(x))
        idx.emplace_back(i);
    if (idx.size() >= (n + 4) / 5) {
      for (auto u : idx) std::cout << u << ' ';
      std::cout << '\n';
    } else {
      std::cout << "-1\n";
    }
    return;
  }
  std::cout << "-1\n";
}

int32_t main() {
#ifdef ORZXKR
  freopen("in.txt", "r", stdin);
  freopen("out.txt", "w", stdout);
#endif
  std::ios::sync_with_stdio(0), std::cin.tie(0), std::cout.tie(0);
  int T = 1;
  std::cin >> T;
  while (T--) dickdreamer();
  // std::cerr << 1.0 * clock() / CLOCKS_PER_SEC << "s\n";
  return 0;
}

标签:int,题解,CF1361E,好点,kMaxN,ins,leq,James,sum
From: https://www.cnblogs.com/Scarab/p/18122405

相关文章

  • 任务处理【华为OD机试】(JAVA&Python&C++&JS题解)
    一.题目-任务处理在某个项目中有多个任务(用tasks数组表示)需要您进行处理,其中tasks[i]=[si,ei],你可以在si<=day<=ei中的任意一天处理该任务。请返回你可以处理的最大任务数。注:一天可以完成一个任务的处理。输入描述:第一行为任务数量n,1<=n<=100000。后......
  • 跳马【华为OD机试】(JAVA&Python&C++&JS题解)
    一.题目马是象棋(包括中国象棋和国际象棋)中的棋子,走法是每步直一格再斜一格,即先横着或直着走一格,然后再斜着走一个对角线,可进可退,可越过河界,俗称“马走‘日’字。给顶m行n列的棋盘(网格图),棋盘上只有有棋子象棋中的棋子“马”,并且每个棋子有等级之分,等级为k的马可以跳1~k......
  • AT_abc348_e 的题解
    (一)感觉D>E。考虑换根DP,把节点\(1\)当作一开始的根节点。先搜一遍,把\(f(1)\)算出。当将计算的节点从父结点往子节点转移时,每个节点到计算的节点的距离要么\(-1\)要么\(+1\),取决于是否在子节点的子树内。可以提前处理字数内\(C\)的值的和,来计算\(f\)的变化量。(二)......
  • CF1292B 题解
    Aroma'sSeatch题意简述题目链接。一个二维平面内有无限个点,从\(0\)开始编号,编号为\(0\)的点的坐标为\((x_{0},y_{0})\)。对于一个编号为\(i(i>0)\)的点,它的坐标为\((a_{x}\cdotx_{i-1}+b_{x},a_y\cdoty_{i-1}+b_{y})\)。Aroma最开始在点\((x_s,y_s)\)处,她每......
  • CF1744F MEX vs MED 题解
    题目传送门题目大意给定一个数列,求满足\(\operatorname{mex}(a_l\sima_r)>\operatorname{med}(a_l\sima_r)\)的区间\([l,r]\)的个数。解题思路记\(p_i\)为\(i\)出现的位置。我们可以枚举\(d\),先确定\(\operatorname{mex}(a_l\sima_r)>d\)的区间。由于数列是\(......
  • CF1951E No Palindromes 题解
    题目大意给出一个字符串sss,要求将sss分为若干个非回文子串,输出......
  • 谢启鸿高等代数第四版习题7.7部分习题解析part2.以及部分第7章复习题
    7.7部分定理:以为特征值的K阶若当块个数为11.设n阶矩阵A的特征值全为1,求证:对任意的正整数K,与A相似。证明:=(易证故此处不再证明)而且的特征值全为1。的特征值为1的k阶若当块的个数为接下来只需证明相似于即可;即证明两者有相同的约当标准型.由书上7.8节的数学归纳可以知道......
  • Unity编辑器中运行正常,发布后报shader为null异常问题解决方案
    在Unity中,Shader是从代码中进行加载的,编辑器中并没有引用。在编辑器中运行项目没有问题,但当项目发布到移动平台,如ios、android、UWP之后,游戏中并不能找到对应的shader。因为Shader在场景中并未被引用,所以没有被打包。解决办法1在ProjectSettings里面的Graphics,添加上修改的打包......
  • P4462 题解
    题目传送门请确保您接触过莫队再阅读此文:对于所有询问,和普通莫队一样的分块然后排序。在这里只讨论add和del操作的具体实现。题目中需要求一段区间的异或值,所以我们可以预处理序列\(a\)的“前缀异或值”pre_xor,题目中的\(a_x\bigoplusa_{x+1}\bigoplus\dots\bigopl......
  • ABC348G题解
    令\(f_i\)为当\(k=i\)时的答案。令\(g_i\)为\(f_i+\max\limits_{j\inS}b_j\)。也就是不减去\(b\)的最大值的结果。直接做是\(O(n^2)\)的,考虑分治,令两个子问题的\(f,g\)分别为\(fl,gl\)和\(fr,gr\)。合并的时候做一个\[f_i=\max(\max\limits_{c+d=i}(gl_c+fr......