简介

首先需要复习一下图论的一系列知识,理解有向图的强连通分量的定义,求解有向图的强连通分量算法有很多,例如Kosaraju,Gabow和Tarjan算法,其中Gabow和Tarjan算法时间复杂度要优于Kosaraju。在这里我们使用Tarjan求解SCC。
在此之前你可以对SCC有个直观的认识,放图:

然后看一篇浅显的说明性的文字,了解这个算法的思想:
http://www.voidcn.com/blog/wr132/article/p-4891712.html
然后我们需要贴一篇经典的文章讲解,传送门如下:
https://www.byvoid.com/blog/scc-tarjan/

理解:

核心思想:一个强连通分量中任意两个节点一定是互相可达的,那么这个强连通分量的从i到j的路径构成一个环(when i=j),因此我们的核心思想就是寻找环。
1. DFN[i]数组存储第i个节点的访问时间time,LOW[i]数组存储当前第i个节点能够直接或者间接访问到的最早的节点的时序time
2. 本算法基于DFS,当遍历到第i个节点的时候,递归结束的条件就是考虑第i个节点的DFN值和LOW是否相等,通俗点说就是这个点能找到的最小时间的点是自身,即从i出发可以回到i,那么i后面遍历到的点包括i在内构成了一个有向图的强连通分量。
3. 其次我们考虑递归遍历的时候,第i个节点的下一个节点i+1如果遍历完毕,我们考虑i+1的LOW值,取i和i+1的LOW值中小的;如果i+1在栈中,说明之前遍历过,如果DFN值小,说明之前遍历过,从当前i到i+1很可能构成环,取之。
下面用一道CCF的题目应用一下SCC算法。


问题描述
  某国有n个城市,为了使得城市间的交通更便利,该国国王打算在城市之间修一些高速公路,由于经费限制,国王打算第一阶段先在部分城市之间修一些单向的高速公路。
  现在,大臣们帮国王拟了一个修高速公路的计划。看了计划后,国王发现,有些城市之间可以通过高速公路直接(不经过其他城市)或间接(经过一个或多个其他城市)到达,而有的却不能。如果城市A可以通过高速公路到达城市B,而且城市B也可以通过高速公路到达城市A,则这两个城市被称为便利城市对。
  国王想知道,在大臣们给他的计划中,有多少个便利城市对。
输入格式
  输入的第一行包含两个整数n, m,分别表示城市和单向高速公路的数量。
  接下来m行,每行两个整数a, b,表示城市a有一条单向的高速公路连向城市b。
输出格式
  输出一行,包含一个整数,表示便利城市对的数量。
样例输入
5 5
1 2
2 3
3 4
4 2
3 5
样例输出
3

题解

  1. 本题思路在于求出SCC,每个SCC内部的任意两个节点都是相互可达的,我们使用C(2n)C\binom{2}{n}就可以求出题目中要求的便利对。这里不要真的使用组合数公式,不要编factorial,稍微化简下就可以得到

    C(2n)=n(n−1)2

    C\binom{2}{n}=\frac{n(n-1)}{2}

  2. 另外使用类似于邻接表的结构存储Graph,例如vector数组,拒绝邻接矩阵,爆内存分分钟的事情。
  3. 注意考虑多连通分量的情况,另外,记得给Graph结构清零处理,很多网上的代码都没有清零处理,AC了CCF的评测是因为数据是递增的,如果数据减少的话,一定是WA。
    下面贴code:
#include <cstdio>
#include <cstring>
#include <stack>
#include <vector>
#include <algorithm>
//#define LOCAL
using namespace std;
//邻接表版本的代码 vector实现
const int N=10005;
int n;          //图结点个数
int DFN[N];
int LOW[N];
int time;       //访问时序
stack<int> s;  //DFS栈
vector<int> G[N];
int vis[N];    //访问数组
int instack[N]; //是否在栈里
int result;void tarjan(int u){DFN[u]=LOW[u]=++time; //time从1开始s.push(u);instack[u]=1;vis[u]=1;for(int j=0;j<G[u].size();j++){int v=G[u][j];if(vis[v]==0){tarjan(v);LOW[u]=min(LOW[u],LOW[v]);}else if(instack[v]){LOW[u]=min(LOW[u],DFN[v]);}}int m;int cnt=0; //连通分量内部的节点数if(DFN[u]==LOW[u]){do{m=s.top();instack[m]=0;s.pop();cnt++;}while(m!=u);if(cnt>1){result+=cnt*(cnt-1)/2; //考虑多个连通分量的情况}}
}
int main(){#ifdef LOCALfreopen("input.txt","r",stdin);#endif // LOCALint m; //边数while(scanf("%d %d",&n,&m)!=EOF){while(s.size()!=0){s.pop();}result=0; //最终结果time=0;memset(vis,0,sizeof(vis));//清空vector比清空struct需要时间少很多memset(G,0,sizeof(G));     memset(DFN,0,sizeof(DFN));memset(LOW,0,sizeof(LOW));memset(instack,0,sizeof(instack));for(int i=0;i<m;i++){int a,b;scanf("%d %d",&a,&b);G[a].push_back(b);}for(int i=1;i<=n;i++){if(vis[i]==0){vis[i]=1;tarjan(i);}}printf("%d\n",result);}return 0;
}

P.S.对于Tarjan算法的理解仍然不够深入,回去补一波算法导论,欢迎各位提出更好的理解建议。

图论 SCC(CCF高速公路)相关推荐

  1. 求无向图的连通分量或有向图的强连通分量—tarjan()ccf高速公路

    概念定义: 在图论中,连通图基于连通的概念. 1. 连通(无向图): 若顶点Vi能通过路径到达Vj,那么称为Vi和Vj是连通的 对无向图:若从顶点Vi到顶点Vj有路径相连(当然从j到i也一定有路径), ...

  2. 图论--SCC缩点--Tarjan

    // Tarjan算法求有向图强连通分量并缩点 /*强连通缩点与双连通缩点大同小异,也就是说将强连通分支缩成一个点之后,没有强连通,成为有向无环图,在对图进行题目的操作.*/ #include< ...

  3. 图论--SCC强连通缩点--Tarjan

    强连通缩点与双连通缩点大同小异,也就是说将强连通分支缩成一个点之后,没有强连通,成为有向无环图,在对图进行题目的操作. // Tarjan算法求有向图强连通分量并缩点 #include<iost ...

  4. HDU 1827 Summer Holiday 图论scc

    先scc缩点,变成DAG,显然ans=入度为0的scc个数,每个scc的答案就是scc内点权最小的值. 1 #include<bits/stdc++.h> 2 #define INF 0x ...

  5. ccf 高速公路(顺便当tarjan模板)

    tarjan算法的模板题,一开始80分,是因为我忘了从每个点都要开始遍历防止多个连通子图的出现 #include<bits/stdc++.h> using namespace std; v ...

  6. 图之强连通、强连通图、强连通分量 Tarjan算法

    一.解释 在有向图G中,如果两个顶点间至少存在一条互相可达路径,称两个顶点强连通(strongly connected).如果有向图G的每两个顶点都强连通,称G是一个强连通图.非强连通图有向图的极大强 ...

  7. 150904 高速公路 ccf

    参考 Kosaraju https://www.cnblogs.com/nullzx/p/6437926.html tarjan https://blog.csdn.net/qq_34374664/a ...

  8. 【图论·强连通分量scc】hdu6072Logical Chain

    非常有灵性的一道强连通分量.乍一看是道模板题,然而需要用bitset优化时间复杂度至1/64:bitset什么鬼啊喂,很佩服赛场上唯一做出来的大佬orz: 常规部分,学习了scc模板求强连通分量: 第 ...

  9. CCF CSP认证菜鸟刷题日志

    CCF CSP菜鸟刷题日志(c/c++) 本萌新写给自己看的,要是有大佬路过,请多多指教orz 立个flag:每日一更,至201903 9月15ccf csp,冲鸭! 今天(2019.8.18)起每天 ...

最新文章

  1. 进入贝壳网_贝壳网app下载安装
  2. 百度编辑器(ueditor)@功能之获取坐标
  3. libuuid 安装
  4. android 5.0新增 ui 控件,android3.0新增ui控件示例说明.doc
  5. DW制作过程基本标准常识
  6. manacher java_最大回文子串(Manacher算法)
  7. 探究Windows内核你知多少
  8. Unity3D跑马灯脚本
  9. Geth私链的多节点运行
  10. 浅谈通过抢注域名获取好域名的小技巧
  11. gulp打包Replace Autoprefixer browsers option to Browserslist config. Use browserslis
  12. 描写火车站场景_优美段落:描写车站的经典美文摘抄
  13. 全国产!全志A40i+Logos FPGA核心板(4核ARM Cortex-A7)硬件说明
  14. 【一种利用插值验证的FL隐私保护框架】VFL: A Verifiable Federated Learning
  15. 迟到的年终总结,2012-2014
  16. Zigbee 设置信道,PANID,发射功率现对z-stack里几个网络参数的设置以及如何获取总结一下。
  17. pycharm 使用conda虚拟环境
  18. 松下PLC FP-XHC60T 程序 两个PLC通信控制11个轴 程序稳定已批量生产 注释完整 带威纶通触摸屏程序
  19. 三网合一”将给中国和中国经济带来什么
  20. Ubuntu 经验 :系统安装 :分区方案

热门文章

  1. NumberRunningTextView改良版
  2. CodeForces - 855B(思维)
  3. Debain 安装SVN服务器 支持http/https 全程指导
  4. 在线2000人的服务器配置,同时线上人数约2000人需要什么等级服务器?
  5. 计算机房防水,机房如何做到防水?
  6. 写好 JavaScript 异步代码的几个技巧
  7. 微信小程序 上滑加载和下拉刷新
  8. 什么是write-allocate policy?
  9. Python 爬取京东商品评论 + 词云展示
  10. 小米路由器编程器强刷breed,可用于救砖,恢复官方系统,恢复SN