CCF 高速公路 tarjan求强连通分量
现在,大臣们帮国王拟了一个修高速公路的计划。看了计划后,国王发现,有些城市之间可以通过高速公路直接(不经过其他城市)或间接(经过一个或多个其他城市)到达,而有的却不能。如果城市A可以通过高速公路到达城市B,而且城市B也可以通过高速公路到达城市A,则这两个城市被称为便利城市对。
国王想知道,在大臣们给他的计划中,有多少个便利城市对。
接下来m行,每行两个整数a, b,表示城市a有一条单向的高速公路连向城市b。
1 2
2 3
3 4
4 2
3 5
城市间的连接如图所示。有3个便利城市对,它们分别是(2, 3), (2, 4), (3, 4),请注意(2, 3)和(3, 2)看成同一个便利城市对。
前60%的评测用例满足1 ≤ n ≤ 1000, 1 ≤ m ≤ 10000;
所有评测用例满足1 ≤ n ≤ 10000, 1 ≤ m ≤ 100000。
- #include <stdio.h>
- #include <string.h>
- #include <iostream>
- #define maxn 200010
- using namespace std;
- struct Node {
- int to;
- int nxt;
- }edge[maxn];
- int head[maxn];
- int tot;
- void addEdge(int u, int v) { // 邻接表形式存储图
- edge[tot].to = v;
- edge[tot].nxt = head[u];
- head[u] = tot++; // head[i] 里存储的是最后一条以i为顶点的边的序号
- }
- int dfn[maxn], low[maxn]; // tarjan 算法的两个数组
- int ord, top; // 当前元素是被访问的序号,模拟栈的首部
- bool instack[maxn]; // 判断该点是否在栈内
- int stac[maxn]; // 栈
- int ans;
- void tarjan(int rt) {
- dfn[rt] = low[rt] = ord++; // 初始化该元素的dfn和low数组
- instack[rt] = true; // 入栈
- stac[++top] = rt;
- for (int i=head[rt]; i!=-1; i=edge[i].nxt) { // 遍历所有以该点为顶点的边
- int v = edge[i].to;
- if (!dfn[v]) { // 如果这个点没有被访问过
- tarjan(v); // 继续向下搜索
- low[rt] = min(low[rt], low[v]); // 更新当前点能回溯到的最远点
- }
- else if (instack[v] && low[rt] > dfn[v]) { //如果已经被访问过 没有被删除 说明这个点是某个强连通分量的一点 当前根的low值和当前点的dfn值比较并更新
- low[rt] = dfn[v]; // 疑问是,这里更新的是low值还是dfn值呢?测试好像谁都可以...
- }
- }
- if (low[rt] == dfn[rt]) { // 找到根 取出当前强连通分量
- int temp = 0;
- int k;
- do {
- k = stac[top--];
- instack[k] = false;
- temp++;
- }while(k!=rt);
- if (temp > 1) {
- ans += (temp*(temp-1))/2;
- }
- }
- }
- int main() {
- int n, m;
- while(cin >> n >> m) {
- memset(head, -1, sizeof(head));
- memset(dfn, 0, sizeof(dfn));
- memset(low, 0, sizeof(low));
- memset(instack, 0, sizeof(instack));
- ord = 0;
- tot = 0;
- top = -1;
- ans = 0;
- for (int i=0; i<m; ++i) {
- int u, v;
- cin >> u >> v;
- addEdge(u, v);
- }
- for (int i=1; i<=n; ++i) { // 依次以所有没被遍历过的点为根尝试搜索强连通分量
- if (!dfn[i])
- tarjan(i);
- }
- cout << ans << endl;
- }
- return 0;
- }
CCF 高速公路 tarjan求强连通分量的更多相关文章
- UESTC 901 方老师抢银行 --Tarjan求强连通分量
思路:如果出现了一个强连通分量,那么走到这个点时一定会在强连通分量里的点全部走一遍,这样才能更大.所以我们首先用Tarjan跑一遍求出所有强连通分量,然后将强连通分量缩成点(用到栈)然后就变成了一个D ...
- tarjan求强连通分量+缩点+割点以及一些证明
“tarjan陪伴强联通分量 生成树完成后思路才闪光 欧拉跑过的七桥古塘 让你 心驰神往”----<膜你抄> 自从听完这首歌,我就对tarjan开始心驰神往了,不过由于之前水平不足,一 ...
- Tarjan求强连通分量,缩点,割点
Tarjan算法是由美国著名计算机专家发明的,其主要特点就是可以求强连通分量和缩点·割点. 而强联通分量便是在一个图中如果有一个子图,且这个子图中所有的点都可以相互到达,这个子图便是一个强连通分量,并 ...
- tarjan求强连通分量+缩点+割点/割桥(点双/边双)以及一些证明
“tarjan陪伴强联通分量 生成树完成后思路才闪光 欧拉跑过的七桥古塘 让你 心驰神往”----<膜你抄> 自从听完这首歌,我就对tarjan开始心驰神往了,不过由于之前水平不足,一 ...
- HDU 1827 Summer Holiday(tarjan求强连通分量+缩点构成新图+统计入度+一点贪心思)经典缩点入门题
Summer Holiday Time Limit: 10000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)T ...
- UVALive 4262——Trip Planning——————【Tarjan 求强连通分量个数】
Road Networks Time Limit:3000MS Memory Limit:0KB 64bit IO Format:%lld & %llu Submit Stat ...
- tarjan求强连通分量(模板)
https://www.luogu.org/problem/P2341 #include<cstdio> #include<cstring> #include<algor ...
- Tarjan求强连通分量、求桥和割点模板
Tarjan 求强连通分量模板.参考博客 #include<stdio.h> #include<stack> #include<algorithm> using n ...
- poj 2186 tarjan求强连通分量
蕾姐讲过的例题..玩了两天后才想起来做 貌似省赛之后确实变得好懒了...再努力两天就可以去北京玩了! 顺便借这个题记录一下求强连通分量的算法 1 只需要一次dfs 依靠stack来实现的tarjan算 ...
随机推荐
- Android实践项目汇报(总结)
天气客户端开发报告 1 系统需求分析 1.1功能性需求分析 天气预报客户端,最基本就是为用户提供准确的天气预报信息.天气查询结果有两种:一种是当天天气信息,信息结果比较详细,除温度.天气状况外还 ...
- Android实验一(在Android Studio中创建项目和模拟器)
北京电子科技学院(BESTI) 实 验 报 告 课程:移动平台开发 班级:1592 姓名:苏泽楠 学号:20159207 成绩: 指导教师 ...
- cron表达式增加一段时间变为新的表达式
cron表达式是使用任务调度经常使用的表达式了.对于通常的简单任务,我们只需要一条cron表达式就能满足.但是有的时候任务也可以很复杂. 最近我遇到了一个问题,一条任务在开始的时候要触发A方法,在结束 ...
- Python3基础 os.path.getsize 获得文件的大小
Python : 3.7.0 OS : Ubuntu 18.04.1 LTS IDE : PyCharm 2018.2.4 Conda ...
- Qt Designer中文入门教程
Qt Designer窗口布局Layouts提供了四种布局方法,他们是: Vertical Layout 纵向布局Horizontal Layout 横向布局Grid Layout 栅格布局Form ...
- P4879 ycz的妹子
思路 让你干啥你就干啥呗 查询第x个妹子就get一下再修改 这里稳一点就维护了三个东西,也许两个也可以 代码 #include <iostream> #include <cstdio ...
- poj3352 Road Construction & poj3177 Redundant Paths (边双连通分量)题解
题意:有n个点,m条路,问你最少加几条边,让整个图变成边双连通分量. 思路:缩点后变成一颗树,最少加边 = (度为1的点 + 1)/ 2.3177有重边,如果出现重边,用并查集合并两个端点所在的缩点后 ...
- MySQL中查询所有数据库占用磁盘空间大小和单个库中所有表的大小的sql语句
查询所有数据库占用磁盘空间大小的SQL语句: ,),' MB') as data_size, concat(,),'MB') as index_size from information_schema ...
- Ubuntu 16.04设置IP、网关、DNS
说明:在网上给的教程上面通常会有这样的一个误导思路,按照配置文件设置后会不生效的问题,甚至没有一点效果,经过排查发现Linux下设置IP这个话题的入口线索应该分为两种:1为Server版,2为Desk ...
- java进制转换代码
定义十进制的数直接写,定义8进制的数以0开头,定义二进制的数以0b开头,定义十六进制的数以0x开头需要将十进制的数以二进制的数表示出来可以参照下例: int a = 10; System.out.pr ...