https://www.luogu.org/problem/P3469

翻译:一个原本连通的无向图,可以删除图中的一个点,求因为删除这个点所导致的不连通的有序点对的数量。或者说,删去这个点之后,各个连通分量的大小的乘积之和?

当然是考虑新学的Tarjan法求割点。一遍Tarjan给每个点记录他是不是割点。然后第二遍的时候对每个割点,统计它分割出的各个子树(及其父亲,假如有的话)这些连通块之间的贡献。

注意无向图是不需要栈的,因为无向图不存在横向边的说法。

错误代码:

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. typedef long long ll;
  4. const int MAXN = 100005;
  5. int n;
  6. vector<int> G[MAXN];
  7. vector<int> T[MAXN];
  8. int dfn[MAXN], low[MAXN], dfncnt;
  9. bool cut[MAXN];
  10. int siz[MAXN];
  11. ll ans[MAXN];
  12. void tarjan(int u, int p) {
  13. low[u] = dfn[u] = ++dfncnt;
  14. siz[u] = 1;
  15. cut[u] = false;
  16. if(p != -1)
  17. T[u].push_back(p);
  18. int ch = 0;
  19. for(auto v : G[u]) {
  20. if(!dfn[v]) {
  21. tarjan(v, u);
  22. T[u].push_back(v);
  23. low[u] = min(low[u], low[v]);
  24. siz[u] += siz[v];
  25. if(p != -1 && low[v] >= dfn[u])
  26. cut[u] = true;
  27. else if(p == -1)
  28. ch++;
  29. } else
  30. low[u] = min(low[u], dfn[v]);
  31. }
  32. if(p == -1 && ch >= 2)
  33. cut[u] = true;
  34. }
  35. bool vis[MAXN];
  36. void dfs(int u, int p) {
  37. vis[u] = 1;
  38. for(auto v : T[u]) {
  39. if(!vis[v])
  40. dfs(v, u);
  41. }
  42. if(cut[u]) {
  43. ll sum = 0;
  44. ans[u] = 0;
  45. for(auto v : T[u]) {
  46. if(v == p) {
  47. sum += n - siz[u];
  48. ans[u] -= 1ll * (n - siz[u]) * (n - siz[u]);
  49. } else {
  50. sum += siz[v];
  51. ans[u] -= 1ll * siz[v] * siz[v];
  52. }
  53. }
  54. ans[u] += sum * sum + 2ll * sum;
  55. } else
  56. ans[u] = 2ll * (n - 1);
  57. }
  58. int main() {
  59. #ifdef Yinku
  60. freopen("Yinku.in", "r", stdin);
  61. #endif // Yinku
  62. int m;
  63. scanf("%d%d", &n, &m);
  64. for(int i = 1, u, v; i <= m; ++i) {
  65. scanf("%d%d", &u, &v);
  66. G[u].push_back(v);
  67. G[v].push_back(u);
  68. }
  69. tarjan(1, -1);
  70. dfs(1, -1);
  71. for(int i = 1; i <= n; ++i) {
  72. printf("%lld\n", ans[i]);
  73. }
  74. return 0;
  75. }

错误原因:某个节点u的子树v中可能出现了反向边(反向到u之前),这棵子树则和u节点的父亲节点等形成了连通块,假如要分段统计,则要在u节点标记哪些子树才是真正会被分开的子树。

那么在这个问题里面对于根节点来说,每棵子树是必定会被分开的,可以统一处理掉。

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. typedef long long ll;
  4. const int MAXN = 100005;
  5. int n;
  6. vector<int> G[MAXN];
  7. int dfn[MAXN], low[MAXN], dfncnt;
  8. ll ans[MAXN];
  9. int siz[MAXN];
  10. void tarjan(int u, int p) {
  11. low[u] = dfn[u] = ++dfncnt;
  12. siz[u] = 1;
  13. ll sum=0;
  14. int ch = 0;
  15. for(auto v : G[u]) {
  16. if(!dfn[v]) {
  17. tarjan(v, u);
  18. low[u] = min(low[u], low[v]);
  19. siz[u] += siz[v];
  20. if(low[v] >= dfn[u]){
  21. ans[u]+=sum*siz[v];
  22. sum+=siz[v];
  23. }
  24. } else
  25. low[u] = min(low[u], dfn[v]);
  26. }
  27. ans[u]+=(n-1-sum)*sum;
  28. ans[u]+=(n-1);
  29. ans[u]*=2ll;
  30. }
  31. int main() {
  32. #ifdef Yinku
  33. freopen("Yinku.in", "r", stdin);
  34. #endif // Yinku
  35. int m;
  36. scanf("%d%d", &n, &m);
  37. for(int i = 1, u, v; i <= m; ++i) {
  38. scanf("%d%d", &u, &v);
  39. G[u].push_back(v);
  40. G[v].push_back(u);
  41. }
  42. tarjan(1, -1);
  43. for(int i = 1; i <= n; ++i)
  44. printf("%lld\n", ans[i]);
  45. return 0;
  46. }

洛谷 - P3469 - BLO-Blockade - 割点的更多相关文章

  1. 洛谷 P3469 [POI2008]BLO-Blockade (Tarjan,割点)

    P3469 [POI2008]BLO-Blockade https://www.luogu.org/problem/P3469 题目描述 There are exactly nn towns in B ...

  2. 【洛谷 P3469】[POI2008]BLO-Blockade(割点)

    题目链接 题意:一个无向联通图,求删去每个点及其所有边后有多少有序点对的连通性发生了变化. Tarjan求割点的例题.. 如果当前点不是割点,那么它对整个图的连通性不产生影响,只有自己与其他\(n-1 ...

  3. 【洛谷P3469】BLO

    题目大意:给定 N 个点,M 条边的联通无向图,求出对于每个点来说,将与这个点相连的所有边都去掉后,会少多少个联通的点对 (x,y). 题解:连通性问题从 DFS 树的角度进行考虑.对于 DFS 树当 ...

  4. 「洛谷P3469」[POI2008]BLO-Blockade 解题报告

    P3469[POI2008]LO-Blockade 题意翻译 在Byteotia有n个城镇. 一些城镇之间由无向边连接. 在城镇外没有十字路口,尽管可能有桥,隧道或者高架公路(反正不考虑这些).每两个 ...

  5. 洛谷P3469[POI2008]BLO-Blockade

    题目 割点模板题. 可以将图中的所有点分成两部分,一部分是去掉之后不影响图的连通性的点,一部分是去掉之后影响连通性的点,称其为割点. 然后分两种情况讨论,如果该点不是割点,则最终结果直接加上2*(n- ...

  6. 【洛谷P3469】[POI2008]BLO-Blockade

    BLO-Blockade 题目链接 若一个点为割点:统计出每个子树的大小,两两相乘再相加, 再加上n-1,为这个点与其他点的拜访数, 因为拜访是互相的,最后再乘二即可 若一个点不是割点:只有(n-1) ...

  7. 【洛谷P3388】(模板)割点

    [模板]割点 割点集合:一个顶点集合V,删除该集合的所有定点以及与这些顶点相连的边后,原图不连通,就称集合V为割点集合 点连通度:最小割点集合中的顶点数 边连通度:最小割边集合中的边数 割点:割点集合 ...

  8. 洛谷 [P3496] BLO

    割点 首先 tarjan 求割点, 对于不是割点的点, 答案是 2 * (n-1) 有序,所以要乘 2 对于是割点的点, 答案是删去该点后所有连通块的个数加上 n-1 在乘 2 #include &l ...

  9. 洛谷 P3469 [POI2008]BLO-Blockade 题解

    一道经典的割点例题,用size数组记录该子树有多少个节点,sum是这棵搜索树上有多少个节点,sum*(n-sum-1)是将点删掉后的数对数量. #include<iostream> #in ...

随机推荐

  1. 我不熟悉的set

    同样的我着重介绍那些我不怎么用到的系列,同时,常用的我就点一下. 我们都知道set底层是用红黑树实现的,红黑树是一种已排序的树,所以我们通过迭代器来访问节点元素的时候,并不可以改变它,如果随意改变,那 ...

  2. Springboot(九).多文件上传下载文件(并将url存入数据库表中)

    一.   文件上传 这里我们使用request.getSession().getServletContext().getRealPath("/static")的方式来设置文件的存储 ...

  3. [洛谷P5361][SDOI2019]热闹又尴尬的聚会:构造题

    分析 构造方法 (截图自UOJ群) 可以使用std::set维护这个过程,不过据说可以做到\(O(n+m)\).. 正确性证明 题目中的要求等价于\((p+1)(q+1) > n\) 设每次找出 ...

  4. nginx负载均衡 理解与测试

    Nginx负载均衡概述 Web服务器,直接面向用户,往往要承载大量并发请求,单台服务器难以负荷,我使用多台WEB服务器组成集群,前端使用Nginx负载均衡,将请求分散的打到我们的后端服务器集群中,实现 ...

  5. go.js-拖拽流程图插件

    1.去除水印 在文件中搜索7eba17a4ca3b1a8346,找到类似a.Jv=d[w.Jg("7eba17a4ca3b1a8346")][w.Jg("78a118b7 ...

  6. 关于Hibernate中Java实体类加载出现序列化异常

    晚上跟着教程敲网上商城项目的时候(ssh框架写的),碰到了一个问题,就是如题所示的序列化异常问题,这个问题纠结了很久,最后发现了一个解决方法,虽然这篇文章可能几乎不会被人访问到,但是还是要写出来! 其 ...

  7. Retrofitting Analysis

    Retrofitting Analysis To figure out the process of retrofitting[1] objective updating, we do the fol ...

  8. python - jpype模块,python调用java的接口

    转载自: http://www.cnblogs.com/junrong624/p/5278457.html https://www.cnblogs.com/fanghao/p/7745356.html ...

  9. Nova rebuild for boot from volume issue

    目录 文章目录 目录 Nova boot from volume Rebuild Instance Rebuild for boot from volume Nova boot from volume ...

  10. Activity启动场景Task分析(二)

    场景分析 下面通过启动Activity的代码来分析一下: 1.桌面 首先,我们看下处于桌面时的状态,运行命令: adb shell dumpsys activity 结果如下 ACTIVITY MAN ...