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

这个东西有点绕。

最平凡的情况,整个原图只有一个点,那么它坍塌了之后就没有点了,不需要进行任何逃生。否则,当一个点坍塌之后,每个其他点的工人都要逃向逃生出口。

首先把双连通分量缩点,缩点完成之后必定是一片森林,树与树之间是乘法原理。

单独考虑一棵树。

平凡的情况,只有一个根节点,没有边。

这种情况下,假如原图中该双连通分量中有>=2个点,则这个双连通分量中要建立2个出口(其中一个出口坍塌了,都可以从另一个出口走),否则假如只有一个点,则只需要建立1个出口。

不平凡的情况,是一棵无根树。必定存在叶子,每个叶子都必须建立1个出口。这个出口必须建立在非原图割点的位置,假如原图这个双连通分量没有割点(这个双连通分量只有一个点,去掉都没没事),则不需要加。

不是叶子的情况,当其他节点坍塌,则必定可以去到至少1个叶子节点逃生,不需要建立逃生出口。当自己(且自己只有一个点)坍塌,每个子树自己跑去自己的叶子就可以了。

那么先特判掉n=1的情况。然后在原图中跑出原图的割点。然后遍历一遍原图的点,从没有被访问过的非割点进入,搜索连接的所有非割点,这些非割点都属于这个双连通分量,而搜索到的割点也属于这个双连通分量不过不需要进去。这样会漏掉两个割点之间的所有非割点和割点,不过这貌似没有问题?因为假如都有两个非割点了,答案就是0了。而且环的另一个半(或者1/3,或者1/4)也会搜索到那两个割点的,反正都是0。

假如只有一个割点,则这个是缩点后图的叶子,贡献C(非割点数量,1)。

假如有多于两个割点,则不贡献,少数的非割点和割点都无所谓了

假如没有割点,则这个双连通分量缩点之后只剩下自己一个点作为树,那么也是贡献C(非割点数量,2),(当该双连通分量有多于两个点时),或者0(当该双连通分量只有1个点时)。

各个双连通分量之间选点独立,各个树之间选点独立,全部乘法叠加。

从这道题可以得到一个常识:每个割点不一定仅属于一个双连通分量,比如一个dio型图。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll; const int MAXN = 505; int n;
vector<int> G[MAXN]; int dfn[MAXN], low[MAXN], dfncnt;
bool cut[MAXN];
int vis[MAXN], viscol;
int cntcut, cntncut; void init() {
for(int i = 1; i <= 500; ++i)
G[i].clear();
dfncnt = 0;
memset(cut, false, sizeof(cut));
memset(vis, false, sizeof(vis));
memset(dfn, false, sizeof(dfn));
memset(low, false, sizeof(low));
viscol = 1;
} void tarjan(int u, int p) {
low[u] = dfn[u] = ++dfncnt;
ll sum = 0;
int ch = 0;
for(auto v : G[u]) {
if(!dfn[v]) {
tarjan(v, u);
low[u] = min(low[u], low[v]);
if(p == -1)
ch++;
else if(low[v] >= dfn[u])
cut[u] = true;
} else
low[u] = min(low[u], dfn[v]);
}
if(ch >= 2)
cut[u] = true;
} void dfs(int u, int p) {
//cout << "u=" << u << endl;
vis[u] = viscol;
++cntncut;
for(auto v : G[u]) {
if(vis[v] != viscol) {
vis[v] = viscol;
if(cut[v])
++cntcut;
else
dfs(v, u);
}
}
} int main() {
#ifdef Yinku
freopen("Yinku.in", "r", stdin);
#endif // Yinku
int m, kase = 1;
while(~scanf("%d", &m)) {
if(m == 0)
return 0;
init();
n = 0;
for(int i = 1, u, v; i <= m; ++i) {
scanf("%d%d", &u, &v);
G[u].push_back(v);
G[v].push_back(u);
n = max(n, max(u, v));
}
for(int i = 1; i <= n; ++i) {
if(!dfn[i])
tarjan(i, -1);
/*if(cut[i])
printf("cut=%d\n",i);*/
}
unsigned long long sum1 = 0;
unsigned long long sum2 = 1;
for(int i = 1; i <= n; ++i) {
if(!vis[i] && !cut[i]) {
//cout<<"viscol="<<viscol<<endl;
cntcut = cntncut = 0;
dfs(i, -1);
if(cntcut == 0) {
if(cntncut >= 2) {
sum1 += 2;
sum2 *= cntncut * (cntncut - 1) / 2;
} else {
sum1 += 1;
}
} else if(cntcut == 1) {
++sum1;
sum2 *= cntncut;
} else
;
viscol++;
}
}
printf("Case %d: %llu %llu\n", kase++, sum1, sum2);
}
return 0;
}

洛谷 - P3225 - 矿场搭建 - 双连通分量的更多相关文章

  1. BZOJ2730:[HNOI2012]矿场搭建(双连通分量)

    Description 煤矿工地可以看成是由隧道连接挖煤点组成的无向图.为安全起见,希望在工地发生事故时所有挖煤点的工人都能有一条出路逃到救援出口处.于是矿主决定在某些挖煤点设立救援出口,使得无论哪一 ...

  2. Tarjan 点双+割点+DFS【洛谷P3225】 [HNOI2012]矿场搭建

    P3225 [HNOI2012]矿场搭建 题目描述 煤矿工地可以看成是由隧道连接挖煤点组成的无向图.为安全起见,希望在工地发生事故时所有挖煤点的工人都能有一条出路逃到救援出口处.于是矿主决定在某些挖煤 ...

  3. 洛谷 P3225 [HNOI2012]矿场搭建 解题报告

    P3225 [HNOI2012]矿场搭建 题目描述 煤矿工地可以看成是由隧道连接挖煤点组成的无向图.为安全起见,希望在工地发生事故时所有挖煤点的工人都能有一条出路逃到救援出口处.于是矿主决定在某些挖煤 ...

  4. 洛谷——P3225 [HNOI2012]矿场搭建

    P3225 [HNOI2012]矿场搭建 题目描述 煤矿工地可以看成是由隧道连接挖煤点组成的无向图.为安全起见,希望在工地发生事故时所有挖煤点的工人都能有一条出路逃到救援出口处.于是矿主决定在某些挖煤 ...

  5. 【洛谷P3225】[HNOI2012]矿场搭建

    矿场搭建 题目链接 根据题意,发生事故时会有一个挖煤点坍塌, 只有当这个点是割点,会对图的连通性产生影响, 我们首先Tarjan一遍找到所有割点,将原图除去这些割点后, 遍历一遍,找出所有连通块,分三 ...

  6. Solution -「洛谷 P5827」边双连通图计数

    \(\mathcal{Description}\)   link.   求包含 \(n\) 个点的边双连通图的个数.   \(n\le10^5\). \(\mathcal{Solution}\)    ...

  7. Solution -「洛谷 P5827」点双连通图计数

    \(\mathcal{Description}\)   link.   求有 \(n\) 个结点的点双连通图的个数,对 \(998244353\) 取模.   \(n\le10^5\). \(\mat ...

  8. 洛谷P3225 HNOI2012 矿场搭建

    题目描述 煤矿工地可以看成是由隧道连接挖煤点组成的无向图.为安全起见,希望在工地发生事故时所有挖煤点的工人都能有一条出路逃到救援出口处.于是矿主决定在某些挖煤点设立救援出口,使得无论哪一个挖煤点坍塌之 ...

  9. 洛谷—— P3225 [HNOI2012]矿场搭建

    https://www.luogu.org/problem/show?pid=3225 题目描述 煤矿工地可以看成是由隧道连接挖煤点组成的无向图.为安全起见,希望在工地发生事故时所有挖煤点的工人都能有 ...

随机推荐

  1. Acwing:137. 雪花雪花雪花(Hash表)

    有N片雪花,每片雪花由六个角组成,每个角都有长度. 第i片雪花六个角的长度从某个角开始顺时针依次记为ai,1,ai,2,…,ai,6ai,1,ai,2,…,ai,6. 因为雪花的形状是封闭的环形,所以 ...

  2. 12.并发编程--Queue

    并发编程--Queue Queue - 非阻塞队列 - 阻塞队列 Queue是一种特殊的线性表,它只允许在表的前端(front)进行删除操作,而在表的后端(rear)进行插入操作.进行插入操作的端称为 ...

  3. centos文件实时同步inotify+rsync

    我的应用场景是重要文件备份 端口:873,备份端打开即可 下载地址:https://rsync.samba.org/ftp/rsync/src/ 服务端和客户端要保持版本一致 网盘链接:https:/ ...

  4. TCP定时器 之 连接建立定时器

    当服务器收到新的syn请求,会回复syn+ack给请求端,若某时间内未收到请求端回复的ack,新建连接定时器超时执行回调,重传syn+ack,当超时超过固定次数时,该连接中止:本文主要分析其初始化流程 ...

  5. 后盾网lavarel视频项目---lavarel多表关联一对多操作实例

    后盾网lavarel视频项目---lavarel多表关联一对多操作实例 一.总结 一句话总结: 1.一对多中多那个部分的数据前端通过json弄到服务器 2.所有通过一操作多的时候,都要用上模型中定义的 ...

  6. android 播放音乐媒体文件(三)

    看段小代码: mMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);mMediaPlayer.setDataSource(url);mM ...

  7. PHP CI 框架初识(一)

    CodeIgniter 是一个简单快速的PHP MVC框架.EllisLab 的工作人员发布了 CodeIgniter.CodeIgniter 是一套小巧但功能强大的.给 PHP 网站开发者使用的 W ...

  8. SHELL中执行Oracle SQL语句查询性能视图

    数据库日志是否报错信息 vi check_log.sh #!/bin/bash # Created : 2019.10.10 # Updated : # Author : # Description ...

  9. LinuxGPIO中文文档

    本文来自Linux官方文档英文版,由于需要使用Linux的GPIO进行实验,我翻译了这篇文档. 本文档描述了GPIO框架的使用者接口.注意它描述了新的基于描述符的接口. 不推荐使用的基于整数的GPIO ...

  10. netfilter/iptables 防火墙

    目录 文章目录 目录 iptables 与 netfilter 工作机制 规则(Rules) 链(chain) 表(tables) 网络数据包通过 iptables 的过程 总结链.表和规则的关系 i ...