CCF 201509-4 高速公路
2016-02-26 23:57
309 查看
问题描述
这道题考察的是有向图连通分量的求法,容易想到的是正反遍历两遍图的所有节点,若均能到达则为连通分量;百度了一下,发现求强连通分量主要有Tarjan和kosaraju两种算法。本题我采用的是Tarjan算法。算法思想百度就有很多,这里不再赘述,我本人主要参考的是这篇 文章里的思路来写的代码。其他可以参考的还有这篇
。
但是这里我的代码上传之后只得到了40分,具体原因我也不是很清楚,对照了一下自己的代码与标准答案,并没有发现什么错误。希望能有好心人帮我指出一下错误在哪,谢谢!
其实这篇大概在初八的样子就应该放上来的,只不过因为自己偷懒,再加上最近又在忙物联网创新大赛的事,因此就一直拖到了现在。。。CCF400分果然还是有难度啊,不知道一个月的时间能不能抓紧补上来。感觉自己三月份应该会很忙的样子,还要准备考研的事,真是痛苦。。。
2016/2/27添加:
重新写了一遍代码,然后发现我之前参考的那篇文章思路是错的。。。我也是有点醉。参考后面那篇文章写的代码之后分数提高到了60分,算法思路应该没有什么问题了,提示的错误是代码超时。对照了一下标准答案,发现标准答案里根本就没用class,而是用了大量的数组与vector来模拟了整个图的数据结构。我觉得应该是自己设计的数据结构访问太慢的原因,晚点会尝试把我的代码再改一下。
PS:尝试着使用了一下dev c++,感觉真是难用。。。现在才真切感受到一个好的IDE对于编程是有多么大的提升。。。
2016/2/29添加:
第三次尝试编写Tarjan算法,这次将图的所有数据全部用数组和vector来存储,果然用时降到了200+ms,但问题是这个程序只有80分!80分!我都快要疯了。。。死活查不出错误在哪。。。只能等我之后有心情再来重新写了。。。
试题编号: | 201509-4 |
试题名称: | 高速公路 |
时间限制: | 1.0s |
内存限制: | 256.0MB |
问题描述: | 问题描述 某国有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。 |
。
但是这里我的代码上传之后只得到了40分,具体原因我也不是很清楚,对照了一下自己的代码与标准答案,并没有发现什么错误。希望能有好心人帮我指出一下错误在哪,谢谢!
#include<iostream> #include<stack> #include<vector> #include<algorithm> using namespace std; const int white = 1; //未访问 const int gray = 0; //正在栈中 const int black = -1; //已访问完毕 int time = 1; //时间戳 long long int ans = 0; //解答 vector<int> vect[10010]; int cnt = 0; stack<int> sta; //访问顺序栈 class EdgeNode{ //边表节点 public: int adjvex; EdgeNode *next = NULL; }; class VertexNode{ //顶点表节点 public: int adjvex; int color; int dfn; int low; EdgeNode *firstedge; }node[10010]; void tarjan(int i) { sta.push(i); node[i].color = gray; node[i].dfn = node[i].low = time++; EdgeNode *temp = node[i].firstedge; while (temp) { int u = temp->adjvex; if (node[u].color == white) { tarjan(u); node[i].low = min(node[i].low, node[u].low); } else if (node[u].color == gray) node[i].low = min(node[i].low, node[u].dfn); temp = temp->next; } node[i].color = black; if (node[i].low == node[i].dfn) { cnt++; int j; do { j = sta.top(); node[j].color = black; sta.pop(); vect[cnt].push_back(j); } while (i != j); } } int main() { int m, n, a, b; cin >> n >> m; for (int i = 1; i <= n; i++) { node[i].adjvex = i; node[i].color = white; } for (int i = 1; i <= m; i++) { cin >> a >> b; EdgeNode *e=new EdgeNode(); e->adjvex = b; e->next = node[a].firstedge; node[a].firstedge = e; } for (int i = 1; i <= n; i++) if (node[i].color == white) tarjan(i); for (int i = 1; i <= cnt; i++) { vector<int> vec = vect[i]; int sz = vec.size(); if (sz > 1) ans += sz*(sz - 1) / 2; } cout << ans << endl; // system("pause"); return 0; }
其实这篇大概在初八的样子就应该放上来的,只不过因为自己偷懒,再加上最近又在忙物联网创新大赛的事,因此就一直拖到了现在。。。CCF400分果然还是有难度啊,不知道一个月的时间能不能抓紧补上来。感觉自己三月份应该会很忙的样子,还要准备考研的事,真是痛苦。。。
2016/2/27添加:
重新写了一遍代码,然后发现我之前参考的那篇文章思路是错的。。。我也是有点醉。参考后面那篇文章写的代码之后分数提高到了60分,算法思路应该没有什么问题了,提示的错误是代码超时。对照了一下标准答案,发现标准答案里根本就没用class,而是用了大量的数组与vector来模拟了整个图的数据结构。我觉得应该是自己设计的数据结构访问太慢的原因,晚点会尝试把我的代码再改一下。
PS:尝试着使用了一下dev c++,感觉真是难用。。。现在才真切感受到一个好的IDE对于编程是有多么大的提升。。。
#include<iostream> #include<vector> #include<stack> #include<algorithm> using namespace std; int time=0; long int ans=0; stack<int> sta; vector<int> vec; int cnt=0; class EdgeNode{ public: int adjvex; EdgeNode* next=NULL; }; class VertexNode{ public: int adjvex; EdgeNode* firstedge=NULL; int dfn; int low; bool in_stack; bool visited; }node[10001]; void tarjan(int i){ sta.push(i); node[i].visited=true; node[i].in_stack=true; node[i].dfn=node[i].low=++time; EdgeNode *temp=node[i].firstedge; while(temp){ int u=temp->adjvex; if(!node[u].visited){ tarjan(u); node[i].low=min(node[i].low,node[u].low); } else if(node[u].in_stack) { node[i].low=min(node[i].low,node[u].dfn); } temp=temp->next; } if(node[i].low==node[i].dfn){ int j,cnt=0; do{ j=sta.top(); node[j].in_stack=false; sta.pop(); cnt++; }while(i!=j); if(cnt!=1) vec.push_back(cnt); } } int main(){ int n,m,a,b; cin>>n>>m; for(int i=1;i<=m;i++){ node[i].adjvex=i; node[i].in_stack=false; node[i].visited=false; } for(int i=0;i<m;i++){ cin>>a>>b; EdgeNode *e=new EdgeNode(); e->adjvex=b; e->next=node[a].firstedge; node[a].firstedge=e; } for(int i=1;i<=n;i++) if(!node[i].visited) tarjan(i); for(int i=0;i<vec.size();i++){ ans+=vec[i]*(vec[i]-1)/2; } cout<<ans<<endl; return 0; }
2016/2/29添加:
第三次尝试编写Tarjan算法,这次将图的所有数据全部用数组和vector来存储,果然用时降到了200+ms,但问题是这个程序只有80分!80分!我都快要疯了。。。死活查不出错误在哪。。。只能等我之后有心情再来重新写了。。。
#include<iostream> #include<vector> #include<stack> #include<algorithm> #include<string.h> using namespace std; int dfn[10001]; int low[10001]; bool in_stack[10001]; bool visited[10001]; vector<int> graph[10001]; stack<int> sta; int time=0; int ans=0; void tarjan(int i) { sta.push(i); in_stack[i]=true; visited[i]=true; dfn[i]=low[i]=++time; int temp=0; while(temp<graph[i].size()) { int n=graph[i][temp++]; if(!visited ) { tarjan(n); low[i]=min(low[i],low ); } else if(in_stack[i]) low[i]=min(low[i],dfn ); } if(dfn[i]==low[i]) { int count=0,j=0; do{ j=sta.top(); in_stack[j]=false; sta.pop(); count++; }while(j!=i); ans+=count*(count-1)/2; } } int main() { int m,n,a,b; cin>>n>>m; memset(dfn,0,(n+1)*sizeof(int)); memset(low,0,(n+1)*sizeof(int)); memset(in_stack,false,(n+1)*sizeof(bool)); memset(visited,false,(n+1)*sizeof(bool)); for(int i=0;i<m;i++){ cin>>a>>b; graph[a].push_back(b); } for(int i=1;i<=n;i++) if(!visited[i]) tarjan(i); cout<<ans<<endl; return 0; }
相关文章推荐
- C 语言算法排序 希尔
- Android Fragment
- mac下配置jsp开发环境——tomcat安装及配置
- Android--Dialog对话框
- thinkphp使用js实现点击加载更多后, 底部无刷新加载出新的数据并显示在该页
- 【学习笔记】day1_快速入门 03_Android体系结构
- Leetcode ☞ 238. Product of Array Except Self ☆
- 外键的使用
- CoInitializeEx 与CoInitialize的区别
- 在Ubuntu上安装使用Systemtap
- 328. Odd Even Linked List
- DirectX SDK 与 DirectShow SDK
- 2016/2/26 jQuery的技术 1,安装 2,语法选择器$ 事件触发 3,常用jQuery函数
- ssh2-hibernate错误小结
- 完美实现tab和Fragment的联动效果
- 19. Remove Nth Node From End of List
- [Leetcode]220. Contains Duplicate III @python
- iOS开发系列--Objective-C之类和对象
- 如何检查内存泄露问题
- Java [Leetcode 136]Single Number