150904 高速公路 ccf
参考
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,则这两个城市被称为便利城市对。 国王想知道,在大臣们给他的计划中,有多少个便利城市对。
输入格式
输入的第一行包含两个整数n, m,分别表示城市和单向高速公路的数量。
接下来m行,每行两个整数a, b,表示城市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相关推荐
- CCF认证历年真题 满分代码(更新至2018年12月)
目标是集齐所有CCF认证试题的满分代码! 每次考试出题一般规律: 第一题:水题(稍微有些编程经验就可以写) 第二题:小模拟(处理比较简单的问题,掌握C++STL很有帮助) 第三题:大模拟(处理复杂的问 ...
- CCF认证历年真题 满分代码
目标是集齐所有CCF认证试题的满分代码! 每次考试出题一般规律: 第一题:水题(稍微有些编程经验就可以写) 第二题:小模拟(处理比较简单的问题,掌握C++STL很有帮助) 第三题:大模拟(处理复杂的问 ...
- 图论 SCC(CCF高速公路)
简介 首先需要复习一下图论的一系列知识,理解有向图的强连通分量的定义,求解有向图的强连通分量算法有很多,例如Kosaraju,Gabow和Tarjan算法,其中Gabow和Tarjan算法时间复杂度要 ...
- 求无向图的连通分量或有向图的强连通分量—tarjan()ccf高速公路
概念定义: 在图论中,连通图基于连通的概念. 1. 连通(无向图): 若顶点Vi能通过路径到达Vj,那么称为Vi和Vj是连通的 对无向图:若从顶点Vi到顶点Vj有路径相连(当然从j到i也一定有路径), ...
- ccf 高速公路(顺便当tarjan模板)
tarjan算法的模板题,一开始80分,是因为我忘了从每个点都要开始遍历防止多个连通子图的出现 #include<bits/stdc++.h> using namespace std; v ...
- CCF认证历年试题解【网上跟帖,请不要使用称呼】
程序改变现实,软件统治世界. 程序员需要有精益求精的工匠精神,追求逻辑的极简.时间的最少和存储的最省,并且懂得其中的平衡. 数据表示需要优先考虑,对于许多问题,找到表示该问题的数据结构,问题自然就解决 ...
- ccf认证俄罗斯方块java_CCF认证历年试题 - osc_h3robkrt的个人空间 - OSCHINA - 中文开源技术交流社区...
CCF认证历年试题 不加索引整理会死星人orz 第一题: CCF201712-1 最小差值(100分) CCF201703-1 分蛋糕(100分) CCF201612-1 中间数(100分) CCF2 ...
- CCF历年真题整理【已更新至202104】
说明:本文持续更新,若长时间未更新,请评论催催我. 以下题目均来自cspro.org,点击进入测试页面,侵删歉. 部分题目我已经解决,并给出参考代码.然而有些我还没有尝试解决,但先把题目贴给大家,大家 ...
- CCF CSP认证菜鸟刷题日志
CCF CSP菜鸟刷题日志(c/c++) 本萌新写给自己看的,要是有大佬路过,请多多指教orz 立个flag:每日一更,至201903 9月15ccf csp,冲鸭! 今天(2019.8.18)起每天 ...
最新文章
- pyspark 连接mysql
- Python下tornado实现webSocket实现
- 第三四五章(PTA复习)
- AJPFX总结String类的特点
- 动画|经典的归并排序究竟怎么玩儿?
- A deep learning model integrating FCNNs and CRFs for brain tumor segmentation
- 电子工业出版社计算机图书出版分社致作者函
- IDL | 实验五 IDL数据可视化
- java学习--基础知识阶段性总结--多线程
- 子界类型(Subrange types)
- 新注册第一帖----------------------乱码新手自学.net 之Linq 入门篇
- HDU-6438丨优先队列
- 微信小程序幻灯片效果实现
- 名帖311 成亲王 行书《杜甫秋兴诗》
- linux su -含义,linux su命令详解步骤
- Windows 10 下安装pycrypto时出错的解决问题
- Python学生管理系统(界面版)
- Android 进度条
- 南京邮电大学微型计算机原理与接口技术:微机系统串行口的测试
- 计算机在我们的生活中应用,计算机在我们生活中的应用