DFS:如何在C++中指示连通分量的节点
我正在制作 ACM 竞赛问题,以确定具有无向图 G 和属于每个组件的顶点的连接组件的数量。已经用DFS算法完成了,计算无向图的连通分量的数量(问题的困难部分),但我想不出任何东西来指示属于每个分量的节点或有节点的记录。
输入: 第一行输入一个整数C,表示测试用例的数量。每个测试用例的第一行包含两个整数 N 和 E,其中 N 表示图中的节点数,E 表示图中的边数。然后是 E 行,每行有 2 个整数 I 和 J,其中 I 和 J 表示节点 I 和节点 J 之间是否存在边(0 ≤ I, J
输出:在每个测试用例的第一行必须显示以下字符串“Case G: P component (s) linked (s)”,其中G代表连接的组件数量测试用例(从 1 开始)和 P 图中连接的组件数量。然后是 X 行,每行包含属于由空格分隔的连接组件的节点(按从最小到最大的顺序)。 每个测试用例之后应该打印一个空行。输出应该写在“output.out”中。
示例:
输入:
2
6 9
0 1
0 2
1 2
5 4
3 1
2 4
2 5
3 4
3 5
8 7
0 1
2 1
2 0
3 4
4 5
5 3
7 6
输出:
Case 1: 1 component (s) connected (s)
0 1 2 3 4 5
Case 2: 3 component (s) connected (s)
0 1 2
3 4 5
6 7
这是我的代码:
#include <stdio.h>
#include <vector>
#include <stdlib.h>
#include <string.h>
using namespace std;
vector<int> adjacency[10000];
bool visited[10000];
/// @param Standard algorithm DFS
void dfs(int u){
visited[ u ] = true;
for( int v = 0 ; v < adjacency[u].size(); ++v ){
if( !visited[ adjacency[u][v] ] ){
dfs( adjacency[u][v] );
}
}
}
int main(int argc, char *argv []){
#ifndef ONLINE_JUDGE
#pragma warning(disable: 4996)
freopen("input.in", "r", stdin);
freopen("output.out", "w", stdout);
#endif
///enumerate vertices from 1 to vertex
int vertex, edges , originNode ,destinationNode, i, j,cont =1;
///number of test cases
int testCases;
int totalComponents;
scanf ("%d", &testCases);
for (i=0; i<testCases; i++){
memset( visited , 0 , sizeof( visited ) );
scanf("%d %d" , &vertex , &edges );
for (j=0; j<edges; j++){
scanf("%d %d" , &originNode ,&destinationNode );
adjacency[ originNode ].push_back( destinationNode );
adjacency[ destinationNode ].push_back( originNode );
}
totalComponents =0;
for( int i = 0 ; i < vertex ; ++i ){ // Loop through all possible vertex
if( !visited[ i ] ){ //if we have not visited any one component from that node
dfs( i ); //we travel from node i the entire graph is formed
totalComponents++; //increased amount of components
}
}
printf("Case %d: %d component (s) connected (s)\n" ,cont++, totalComponents);
for (j=0;j<total;j++){
/*here should indicate the vertices of each connected component*/
}
memset( adjacency , 0 , sizeof( adjacency ) );
}
return 0;
}
我对如何携带属于每个连接组件或结构的节点的内存应该用于存储有疑问,我应该如何修改我的代码来做到这一点?,我想听听建议、想法或任何伪代码的实现。感谢大家
I am making a problem of ACM competitions to determine the number of connected components that have an undirected graph G and vertices belonging to each component. 've Already done with a DFS algorithm, counting the number of connected components of undirected graph (the hard part of problem), but I can not think of anything to indicate the nodes belonging to each component or have a record of the nodes.
Input: The first line of input will an integer C, which indicates the number of test cases. The first line of each test case contains two integers N and E, where N represents the number of nodes in the graph and E the number of edges in it. Then follow E lines, each with 2 integers I and J, where I and J represent the existence of an edge between node I and node J (0 ≤ I, J
Output: In the first line of each test case must display the following string "Case G: P component (s) connected (s)", where G represents the number of test case (starting at 1) and P the number of components connected in the graph. Then X lines, each containing the nodes belonging to a connected component (in order from smallest to largest) separated by spaces.
After each test case should print a blank line. The output should be written in the "output.out."
Example:
Input:
2
6 9
0 1
0 2
1 2
5 4
3 1
2 4
2 5
3 4
3 5
8 7
0 1
2 1
2 0
3 4
4 5
5 3
7 6
Output:
Case 1: 1 component (s) connected (s)
0 1 2 3 4 5
Case 2: 3 component (s) connected (s)
0 1 2
3 4 5
6 7
Here's my code:
#include <stdio.h>
#include <vector>
#include <stdlib.h>
#include <string.h>
using namespace std;
vector<int> adjacency[10000];
bool visited[10000];
/// @param Standard algorithm DFS
void dfs(int u){
visited[ u ] = true;
for( int v = 0 ; v < adjacency[u].size(); ++v ){
if( !visited[ adjacency[u][v] ] ){
dfs( adjacency[u][v] );
}
}
}
int main(int argc, char *argv []){
#ifndef ONLINE_JUDGE
#pragma warning(disable: 4996)
freopen("input.in", "r", stdin);
freopen("output.out", "w", stdout);
#endif
///enumerate vertices from 1 to vertex
int vertex, edges , originNode ,destinationNode, i, j,cont =1;
///number of test cases
int testCases;
int totalComponents;
scanf ("%d", &testCases);
for (i=0; i<testCases; i++){
memset( visited , 0 , sizeof( visited ) );
scanf("%d %d" , &vertex , &edges );
for (j=0; j<edges; j++){
scanf("%d %d" , &originNode ,&destinationNode );
adjacency[ originNode ].push_back( destinationNode );
adjacency[ destinationNode ].push_back( originNode );
}
totalComponents =0;
for( int i = 0 ; i < vertex ; ++i ){ // Loop through all possible vertex
if( !visited[ i ] ){ //if we have not visited any one component from that node
dfs( i ); //we travel from node i the entire graph is formed
totalComponents++; //increased amount of components
}
}
printf("Case %d: %d component (s) connected (s)\n" ,cont++, totalComponents);
for (j=0;j<total;j++){
/*here should indicate the vertices of each connected component*/
}
memset( adjacency , 0 , sizeof( adjacency ) );
}
return 0;
}
I have doubts about how to carry memory of the nodes belonging to each connected component or structure should be used to store, how I should modify my code to do this?, I would like to hear suggestions, ideas or any implementation in pseudocode. Thanks to all
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
算法大致是:
结果是一组“组件”数据结构(我的实现中的 std::vector ),每个数据结构都包含一组专门互连的节点。
注意事项:
std::vector
即可高效地构建此结构。这是工作代码。请注意,使用了一些 C++11 功能,但如果使用较旧的编译器,它们应该很容易替换。错误处理留给读者作为练习。
将此程序称为...
...其中
input.in
包含问题中描述的格式的数据,它将在output.out
中产生所需的结果。The algorithm is roughly:
The result is a set of "component" data structures (
std::vector
s in my implementation), each containing a set of exclusively inter-connected nodes.Considerations:
std::vector
.Here is the working code. Note that some C++11 features were used, but they should be easy to replace if older compiler is used. The error handling is left as exercise for the reader.
Call this program as...
...where
input.in
contains data in format described in your question and it will produce the desired result inoutput.out
.解决方案更简单,您必须声明两个大小为顶点数的数组
然后,当您调用DFS时,每个顶点都存储在顶点数组中,并存储在该组件所属的位置
最后,它打印总组件并创建一个标记为与每个顶点的分量进行比较的第一个分量的值
the solution is much easier, you must declare two arrays of size the number of vertices
Then, when you call to DFS each vertex is stored in the array of vertices, and stored at that component belongs
Finally, it prints the total components and created a flag with the value of the first component which is compared with the component of each vertex
您可以像这样存储组件:
并修改代码:
现在totalComponents是components.size():
请注意,代码未经测试。包含
来获取排序函数。You could store the components like this:
and modify the code:
now totalComponents is components.size() :
Note that the code is not tested. Include
<algorithm>
to get the sort function.测试 2 个节点是否连接的通用算法:
首先,您的节点将各自位于其集合中,
随着算法的进展并合并集合,它相对将输入减半。
在上面的示例中,我想查看 o1 和 o2 之间是否存在路径。我仅在合并所有边后才在最后找到这条路径。有些图表可能有单独的组件(断开连接),这意味着您最终无法拥有一组。在这种情况下,您可以使用此算法来测试连通性,甚至计算图中的组件数量。组件的数量是算法完成时您能够获得的集合的数量。
一个可能的图表(对于上面的树):
General algorithm to test if 2 nodes are connected:
At first your nodes will be each in its set,
As the algorithm progresses and merges the sets, it relatively halves the input.
In the example above I was looking to see if there was a path between o1 and o2. I found this path only at the end after merging all edges. Some graphs may have separate components (disconnected) which entails that you will not be able to have one set at the end. In such a case you can use this algorithm to test for connectedness and even count the number of components in a graph. The number of components is the number of sets you are able to get when the algorithm finishes.
A possible graph (for the tree above):