参考

Kosaraju

https://www.cnblogs.com/nullzx/p/6437926.html

tarjan

https://blog.csdn.net/qq_34374664/article/details/77488976

思路

求回路也就是求图的强连通分量

共有两种算法:Kosaraju与tarjan,其中Kosaraju算法较易理解但需要两次dfs,tarjan算法较难理解但只需dfs一次。

两种算法的详解见参考。

概述:

Kosaraju

1、对图的反向图进行一次逆后序dfs遍历

2、按照逆后序遍历得到的栈中点的出栈顺序对原图进行dfs遍历,每一次遍历访问到的点就属于一个强连通分量。

tarjan

 1 /*
 2 dfn为访问序号(时间戳)
 3 low为当前节点及其子树中结点最小的访问序号,类似并查集
 4 */
 5 void tarjan(int u){
 6
 7   DFN[u]=Low[u]=++Index // 为节点u设定次序编号和Low初值
 8
 9   Stack.push(u)   // 将节点u压入栈中
10
11   for each (u, v) in E // 枚举每一条边
12     {
13             if (v is not visted) // 如果节点v未被访问过
14
15     {
16                 tarjan(v) // 继续向下找
17                 Low[u] = min(Low[u], Low[v])
18             }    
19
20     else if (v in S) // 如果节点u还在栈内
21
22     {   Low[u] = min(Low[u], DFN[v])   }
23     }
24
25   if (DFN[u] == Low[u]) // 如果节点u是强连通分量的根
26    {
27            repeat
28
29            v = S.pop  // 将v退栈,为该强连通分量中一个顶点
30
31        print v
32
33        until (u== v)
34    }
35
36 }                    

tarjan伪代码

实现

Kosaraju

 1 //Kosaraju
 2 #include<bits/stdc++.h>
 3
 4 using namespace std;
 5
 6 #define MAXN 10005
 7
 8 vector<int> Map1[MAXN];
 9 vector<int> Map2[MAXN];
10 stack<int> sta;
11 int vis[MAXN];
12 long long int ans=0,num=0;
13 int n,m;
14
15 int size,v;
16 void dfs2(int s){
17
18     for(int i=0;i<Map2[s].size();i++){
19         v=Map2[s][i];
20         if(vis[v]==0){
21             vis[v]=1;
22             dfs2(v);
23         }
24     }
25     sta.push(s);
26 }
27
28 void dfs1(int s){
29     for(int i=0;i<Map1[s].size();i++){
30         v=Map1[s][i];
31         if(vis[v]==0){
32             //cout<<v<<' ';
33             vis[v]=1;
34             num++;
35             dfs1(v);
36         }
37     }
38 }
39
40 long long int C(int x){
41     if(x<=1){
42         return 0;
43     }
44     else{
45         long long int a=1;
46         for(int i=x;i>x-2;i--){
47             a*=i;
48         }
49         return a/2;
50     }
51 }
52
53 int main(){
54     cin>>n>>m;
55     int a,b;
56     for(int i=0;i<m;i++){
57         cin>>a>>b;
58         Map1[a].push_back(b);
59         Map2[b].push_back(a);
60     }
61
62     memset(vis,0,sizeof(vis));
63     for(int i=0;i<=n;i++){
64         if(vis[i]==0){
65             vis[i]=1;
66             dfs2(i);
67         }
68     }
69
70     memset(vis,0,sizeof(vis));
71     int v;
72     while(!sta.empty()){
73         v=sta.top();
74         sta.pop();
75
76         if(vis[v]==0){
77             //cout<<v<<' ';
78             vis[v]=1;
79             num=1;
80             dfs1(v);
81             //cout<<num<<endl;
82             ans+=C(num);
83         }
84     }
85
86     cout<<ans;
87
88     return 0;
89 }

View Code

tarjan

 1 //tarjan
 2
 3 #include<bits/stdc++.h>
 4
 5 using namespace std;
 6
 7 #define MAXN 10005
 8
 9 vector<int> Map[MAXN];
10 stack<int> sta;
11 int vis[MAXN];
12 int dfn[MAXN];
13 int low[MAXN];
14 int insta[MAXN];
15 long long int num=0,ans=0;
16 int n,m,index;
17
18 long long int C(int x){
19     if(x<=1){
20         return 0;
21     }
22     else{
23         long long int a=1;
24         for(int i=x;i>x-2;i--){
25             a*=i;
26         }
27         return a/2;
28     }
29 }
30
31 void tarjan(int u)
32 {
33     index++;
34     dfn[u]=low[u]=index;
35     vis[u]=1;
36     sta.push(u);
37     insta[u]=1;
38     int  size=Map[u].size();
39     for(int i=0;i<size;i++){
40         int v=Map[u][i];
41         if(vis[v]==0){
42             tarjan(v);
43             low[u]=min(low[u],low[v]);
44         }
45         else if(insta[v]==1){
46             low[u]=min(low[u],dfn[v]);
47         }
48     }
49     num=0;
50     if(dfn[u]==low[u]){
51         int v;
52         do{
53             v=sta.top();
54             //cout<<v<<' ';
55             sta.pop();
56             insta[v]=0;
57             num++;
58         }while(v!=u);
59         //cout<<endl;
60     }
61     ans+=C(num);
62 }
63
64 int main(){
65     cin>>n>>m;
66     int a,b;
67     for(int i=0;i<m;i++){
68         cin>>a>>b;
69         Map[a].push_back(b);
70     }
71     memset(vis,0,sizeof(vis));
72     memset(insta,0,sizeof(insta));
73     index=0;
74     for(int i=1;i<=n;i++){
75         if(vis[i]==0){
76             tarjan(i);
77         }
78     }
79     cout<<ans;
80
81     return 0;
82 }

View Code

题目

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

  城市间的连接如图所示。有3个便利城市对,它们分别是(2, 3), (2, 4), (3, 4),请注意(2, 3)和(3, 2)看成同一个便利城市对。
评测用例规模与约定
前30%的评测用例满足1 ≤ n ≤ 100, 1 ≤ m ≤ 1000;
  前60%的评测用例满足1 ≤ n ≤ 1000, 1 ≤ m ≤ 10000;
  所有评测用例满足1 ≤ n ≤ 10000, 1 ≤ m ≤ 100000。

转载于:https://www.cnblogs.com/Gru-blog/p/11321602.html

150904 高速公路 ccf相关推荐

  1. CCF认证历年真题 满分代码(更新至2018年12月)

    目标是集齐所有CCF认证试题的满分代码! 每次考试出题一般规律: 第一题:水题(稍微有些编程经验就可以写) 第二题:小模拟(处理比较简单的问题,掌握C++STL很有帮助) 第三题:大模拟(处理复杂的问 ...

  2. CCF认证历年真题 满分代码

    目标是集齐所有CCF认证试题的满分代码! 每次考试出题一般规律: 第一题:水题(稍微有些编程经验就可以写) 第二题:小模拟(处理比较简单的问题,掌握C++STL很有帮助) 第三题:大模拟(处理复杂的问 ...

  3. 图论 SCC(CCF高速公路)

    简介 首先需要复习一下图论的一系列知识,理解有向图的强连通分量的定义,求解有向图的强连通分量算法有很多,例如Kosaraju,Gabow和Tarjan算法,其中Gabow和Tarjan算法时间复杂度要 ...

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

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

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

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

  6. CCF认证历年试题解【网上跟帖,请不要使用称呼】

    程序改变现实,软件统治世界. 程序员需要有精益求精的工匠精神,追求逻辑的极简.时间的最少和存储的最省,并且懂得其中的平衡. 数据表示需要优先考虑,对于许多问题,找到表示该问题的数据结构,问题自然就解决 ...

  7. ccf认证俄罗斯方块java_CCF认证历年试题 - osc_h3robkrt的个人空间 - OSCHINA - 中文开源技术交流社区...

    CCF认证历年试题 不加索引整理会死星人orz 第一题: CCF201712-1 最小差值(100分) CCF201703-1 分蛋糕(100分) CCF201612-1 中间数(100分) CCF2 ...

  8. CCF历年真题整理【已更新至202104】

    说明:本文持续更新,若长时间未更新,请评论催催我. 以下题目均来自cspro.org,点击进入测试页面,侵删歉. 部分题目我已经解决,并给出参考代码.然而有些我还没有尝试解决,但先把题目贴给大家,大家 ...

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

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

最新文章

  1. pyspark 连接mysql
  2. Python下tornado实现webSocket实现
  3. 第三四五章(PTA复习)
  4. AJPFX总结String类的特点
  5. 动画|经典的归并排序究竟怎么玩儿?
  6. A deep learning model integrating FCNNs and CRFs for brain tumor segmentation
  7. 电子工业出版社计算机图书出版分社致作者函
  8. IDL | 实验五 IDL数据可视化
  9. java学习--基础知识阶段性总结--多线程
  10. 子界类型(Subrange types)
  11. 新注册第一帖----------------------乱码新手自学.net 之Linq 入门篇
  12. HDU-6438丨优先队列
  13. 微信小程序幻灯片效果实现
  14. 名帖311 成亲王 行书《杜甫秋兴诗》
  15. linux su -含义,linux su命令详解步骤
  16. Windows 10 下安装pycrypto时出错的解决问题
  17. Python学生管理系统(界面版)
  18. Android 进度条
  19. 南京邮电大学微型计算机原理与接口技术:微机系统串行口的测试
  20. 计算机在我们的生活中应用,计算机在我们生活中的应用

热门文章

  1. Cookie工具类的借鉴别人的ThinkGem的代码学习
  2. 85、android handler的警告Handler Class Should be Static or Leaks Occur
  3. LXReorderableCollectionViewFlowLayout
  4. DOM 中的事件处理
  5. Python实战之子进程
  6. 字符串处理 - ANSI - Unicode - UTF8 转换
  7. 蓝桥杯 ALGO30 算法训练 入学考试 java版
  8. 检错码之奇偶校验编码
  9. 【iOS开发】什么是Bundle,每个iOS应用实际上是一个Bundle
  10. 蓝桥杯 BASIC-18 基础练习 矩形面积交