洛谷 - P3469 - BLO-Blockade - 割点
https://www.luogu.org/problem/P3469
翻译:一个原本连通的无向图,可以删除图中的一个点,求因为删除这个点所导致的不连通的有序点对的数量。或者说,删去这个点之后,各个连通分量的大小的乘积之和?
当然是考虑新学的Tarjan法求割点。一遍Tarjan给每个点记录他是不是割点。然后第二遍的时候对每个割点,统计它分割出的各个子树(及其父亲,假如有的话)这些连通块之间的贡献。
注意无向图是不需要栈的,因为无向图不存在横向边的说法。
错误代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MAXN = 100005;
int n;
vector<int> G[MAXN];
vector<int> T[MAXN];
int dfn[MAXN], low[MAXN], dfncnt;
bool cut[MAXN];
int siz[MAXN];
ll ans[MAXN];
void tarjan(int u, int p) {
low[u] = dfn[u] = ++dfncnt;
siz[u] = 1;
cut[u] = false;
if(p != -1)
T[u].push_back(p);
int ch = 0;
for(auto v : G[u]) {
if(!dfn[v]) {
tarjan(v, u);
T[u].push_back(v);
low[u] = min(low[u], low[v]);
siz[u] += siz[v];
if(p != -1 && low[v] >= dfn[u])
cut[u] = true;
else if(p == -1)
ch++;
} else
low[u] = min(low[u], dfn[v]);
}
if(p == -1 && ch >= 2)
cut[u] = true;
}
bool vis[MAXN];
void dfs(int u, int p) {
vis[u] = 1;
for(auto v : T[u]) {
if(!vis[v])
dfs(v, u);
}
if(cut[u]) {
ll sum = 0;
ans[u] = 0;
for(auto v : T[u]) {
if(v == p) {
sum += n - siz[u];
ans[u] -= 1ll * (n - siz[u]) * (n - siz[u]);
} else {
sum += siz[v];
ans[u] -= 1ll * siz[v] * siz[v];
}
}
ans[u] += sum * sum + 2ll * sum;
} else
ans[u] = 2ll * (n - 1);
}
int main() {
#ifdef Yinku
freopen("Yinku.in", "r", stdin);
#endif // Yinku
int m;
scanf("%d%d", &n, &m);
for(int i = 1, u, v; i <= m; ++i) {
scanf("%d%d", &u, &v);
G[u].push_back(v);
G[v].push_back(u);
}
tarjan(1, -1);
dfs(1, -1);
for(int i = 1; i <= n; ++i) {
printf("%lld\n", ans[i]);
}
return 0;
}
错误原因:某个节点u的子树v中可能出现了反向边(反向到u之前),这棵子树则和u节点的父亲节点等形成了连通块,假如要分段统计,则要在u节点标记哪些子树才是真正会被分开的子树。
那么在这个问题里面对于根节点来说,每棵子树是必定会被分开的,可以统一处理掉。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MAXN = 100005;
int n;
vector<int> G[MAXN];
int dfn[MAXN], low[MAXN], dfncnt;
ll ans[MAXN];
int siz[MAXN];
void tarjan(int u, int p) {
low[u] = dfn[u] = ++dfncnt;
siz[u] = 1;
ll sum=0;
int ch = 0;
for(auto v : G[u]) {
if(!dfn[v]) {
tarjan(v, u);
low[u] = min(low[u], low[v]);
siz[u] += siz[v];
if(low[v] >= dfn[u]){
ans[u]+=sum*siz[v];
sum+=siz[v];
}
} else
low[u] = min(low[u], dfn[v]);
}
ans[u]+=(n-1-sum)*sum;
ans[u]+=(n-1);
ans[u]*=2ll;
}
int main() {
#ifdef Yinku
freopen("Yinku.in", "r", stdin);
#endif // Yinku
int m;
scanf("%d%d", &n, &m);
for(int i = 1, u, v; i <= m; ++i) {
scanf("%d%d", &u, &v);
G[u].push_back(v);
G[v].push_back(u);
}
tarjan(1, -1);
for(int i = 1; i <= n; ++i)
printf("%lld\n", ans[i]);
return 0;
}
洛谷 - P3469 - BLO-Blockade - 割点的更多相关文章
- 洛谷 P3469 [POI2008]BLO-Blockade (Tarjan,割点)
P3469 [POI2008]BLO-Blockade https://www.luogu.org/problem/P3469 题目描述 There are exactly nn towns in B ...
- 【洛谷 P3469】[POI2008]BLO-Blockade(割点)
题目链接 题意:一个无向联通图,求删去每个点及其所有边后有多少有序点对的连通性发生了变化. Tarjan求割点的例题.. 如果当前点不是割点,那么它对整个图的连通性不产生影响,只有自己与其他\(n-1 ...
- 【洛谷P3469】BLO
题目大意:给定 N 个点,M 条边的联通无向图,求出对于每个点来说,将与这个点相连的所有边都去掉后,会少多少个联通的点对 (x,y). 题解:连通性问题从 DFS 树的角度进行考虑.对于 DFS 树当 ...
- 「洛谷P3469」[POI2008]BLO-Blockade 解题报告
P3469[POI2008]LO-Blockade 题意翻译 在Byteotia有n个城镇. 一些城镇之间由无向边连接. 在城镇外没有十字路口,尽管可能有桥,隧道或者高架公路(反正不考虑这些).每两个 ...
- 洛谷P3469[POI2008]BLO-Blockade
题目 割点模板题. 可以将图中的所有点分成两部分,一部分是去掉之后不影响图的连通性的点,一部分是去掉之后影响连通性的点,称其为割点. 然后分两种情况讨论,如果该点不是割点,则最终结果直接加上2*(n- ...
- 【洛谷P3469】[POI2008]BLO-Blockade
BLO-Blockade 题目链接 若一个点为割点:统计出每个子树的大小,两两相乘再相加, 再加上n-1,为这个点与其他点的拜访数, 因为拜访是互相的,最后再乘二即可 若一个点不是割点:只有(n-1) ...
- 【洛谷P3388】(模板)割点
[模板]割点 割点集合:一个顶点集合V,删除该集合的所有定点以及与这些顶点相连的边后,原图不连通,就称集合V为割点集合 点连通度:最小割点集合中的顶点数 边连通度:最小割边集合中的边数 割点:割点集合 ...
- 洛谷 [P3496] BLO
割点 首先 tarjan 求割点, 对于不是割点的点, 答案是 2 * (n-1) 有序,所以要乘 2 对于是割点的点, 答案是删去该点后所有连通块的个数加上 n-1 在乘 2 #include &l ...
- 洛谷 P3469 [POI2008]BLO-Blockade 题解
一道经典的割点例题,用size数组记录该子树有多少个节点,sum是这棵搜索树上有多少个节点,sum*(n-sum-1)是将点删掉后的数对数量. #include<iostream> #in ...
随机推荐
- K8S容器探针
容器探针 探针是由 kubelet对容器执行的定期诊断.要执行诊断, kubelet 调用由容器实现的 Handler .有三种类型的处理程序: ExecAction :在容器内执行指定命令 ...
- 【BZOJ3545&BZOJ3551】Peaks(kruskal重构树,主席树,dfs序)
题意:在Bytemountains有N座山峰,每座山峰有他的高度h_i. 有些山峰之间有双向道路相连,共M条路径,每条路径有一个困难值,这个值越大表示越难走, 现在有Q组询问,每组询问询问从点v开始只 ...
- Hexo + github pages + 阿里云绑定域名搭建个人博客
申请域名 万网购买的域名,地址:https://wanwang.aliyun.com/domain/com?spm=5176.8142029.388261.137.LoKzy7 控制台进行解析 控制台 ...
- Vue成员与指令介绍
一.Vue介绍 1.什么是vue 通过对框架的了解与运用程度,来决定其在整个项目中的应用范围, 可以独立完成前后端分离式web项目的渐进式JavaScript框架 2.为什么要学vue 三大主流框架之 ...
- JavaScript 的基本概念( ES5 )
语法 区分大小写 标识符 第一个字符必须是一个字母,下划线或者一个美元符( $ ).其他规则无论,最好按照通用的驼峰大小写. 注释 // 单行注释 /* 多行注释 */ 严格模式 在顶部添加如下代码 ...
- MySQL数据库入门——备份数据库
mysqldump可以针对单个表.多个表.单个数据库.多个数据库.所有数据库进行导出的操作 mysqldump常用选项 -h, --host=name:服务器IP -u, --user=name:登录 ...
- Java 工程师成神之路
基础篇 → 什么是面向对象 面向对象.面向过程 是一种新兴的程序设计方法,或者是一种新的程序设计规范(paradigm),其基本思想是使用对象.类.继承.封装.多态等基本概念来进行程序设计.从现实世界 ...
- 在一般处理程序中使用session
public class Handler1 : IHttpHandler, IRequiresSessionState 需要继承 IRequiresSessionState接口,告诉程序要使用sess ...
- windows环境安装nexus
1.下载安装nexus安装包,我用的是nexus-2.14.13-01版本 2. 以管理员身份打开cmd命令窗口 3.进入到nexus bin目录下 输入命令 nexus install 4. 启动 ...
- java 正则表达式:有丶东西
非常详细 原文地址:https://blog.csdn.net/jeffleo/article/details/52194977