连接未连接的有向图所需的最小边数

huangapple go评论63阅读模式
英文:

Minimum Edge required to connect a unconnected directed graph

问题

我正在尝试编写一个算法,该算法可以找到连接有向非连接图中所有起始顶点的所有节点所需添加的最少边数
```cpp
#include <iostream>
#include <vector>
#include <fstream>

using namespace std;

class Graph {
    vector<vector<int>> vertices;
public:
    Graph(int num_ver) {
        vertices.resize(num_ver);
    }

    void addEdge(int ver1, int ver2) {
        vertices[ver1].push_back(ver2);
    }

    vector<int>& getNeighbors(int ver) {
        return vertices[ver];
    }
    int getVertices() {
        return vertices.size();
    }
};

void dfs(Graph& graph, int vertex, vector<bool>& visited) {
    visited[vertex] = true;
    vector<int>& neighbors = graph.getNeighbors(vertex);
    for (int i = 0; i < neighbors.size(); i++) {
        int n = neighbors[i];
        if (!visited[n]) {
            dfs(graph, n, visited);
        }
    }
}

int findMinEdges(Graph& graph) {
    int num_vertices = graph.getVertices();
    vector<bool> visited(num_vertices, false);
    int edges = 0;
    for (int i = 0; i < num_vertices; i++) {
        if (!visited[i]) {
            dfs(graph, i, visited);
            edges++;
        }
    }
    return (edges - 1);
}

int main() {
    ifstream f("input.txt");
    int vertices, edges, start;
    f >> vertices >> edges >> start;
    //cout << vertices << edges << start;
    Graph g(vertices + 1);
    int v1, v2;
    for (int i = 0; i < edges; i ++) {
        f >> v1 >> v2;
        g.addEdge(v1, v2);
    }
    f.close();
    int min_edges = findMinEdges(g);
    cout << "Minimum number of edges to make the graph connected: " << min_edges << endl;
    ofstream o("output.txt");
    o << min_edges;
    o.close();
    return 0;
}

这段代码使用了一个简单的图数据结构和深度优先搜索算法来尝试实现此目标。我已经尝试在较小的输入上运行代码,它可以正常工作,但当输入规模增大时,它返回错误的答案。我已经尝试使用其他算法,例如Trajan的算法,但即使那个也没有对我起作用。

样本输入文件:

6 5 5
1 2
2 3
3 1
4 5
5 6

前3个数字代表总顶点数、总边数和起始顶点,接下来的行表示边(第一个数字是v1,第二个是v2)。

对于此示例,代码可以正常工作,但对于较大的输入则不行。我似乎无法理解问题出在哪里!

https://file.io/bHnJHoqSE3ji 包含输入文本文件。算法给出的输出是356,而预期输出是263。

英文:

I am trying to write an algorithm that finds the minimum number of edges that are required to be added to connect all nodes from the starting vertices in a directed unconnected graph

#include &lt;iostream&gt;
#include &lt;vector&gt;
#include &lt;fstream&gt;
using namespace std;
class Graph {
vector&lt;vector&lt;int&gt;&gt; vertices;
public:
Graph(int num_ver) {
vertices.resize(num_ver);
}
void addEdge(int ver1, int ver2) {
vertices[ver1].push_back(ver2);
}
vector&lt;int&gt;&amp; getNeighbors(int ver) {
return vertices[ver];
}
int getVertices() {
return vertices.size();
}
};
void dfs(Graph&amp; graph, int vertex, vector&lt;bool&gt;&amp; visited) {
visited[vertex] = true;
vector&lt;int&gt;&amp; neighbors = graph.getNeighbors(vertex);
for (int i = 0; i &lt; neighbors.size(); i++) {
int n = neighbors[i];
if (!visited[n]) {
dfs(graph, n, visited);
}
}
}
int findMinEdges(Graph&amp; graph) {
int num_vertices = graph.getVertices();
vector&lt;bool&gt; visited(num_vertices, false);
int edges = 0;
for (int i = 0; i &lt; num_vertices; i++) {
if (!visited[i]) {
dfs(graph, i, visited);
edges++;
}
}
return (edges - 1);
}
int main() {
ifstream f(&quot;input.txt&quot;);
int vertices, edges, start;
f &gt;&gt; vertices &gt;&gt; edges &gt;&gt; start;
//cout &lt;&lt; vertices &lt;&lt; edges &lt;&lt; start;&#39;
Graph g(vertices + 1);
int v1, v2;
for (int i = 0; i &lt; edges; i ++) {
f &gt;&gt; v1 &gt;&gt; v2;
g.addEdge(v1, v2);
}
f.close();
int min_edges = findMinEdges(g);
cout &lt;&lt; &quot;Minimum number of edges to make the graph connected: &quot; &lt;&lt; min_edges &lt;&lt; endl;
ofstream o(&quot;output.txt&quot;);
o &lt;&lt; min_edges;
o.close();
return 0;
}

The code uses a simple graph data structure and dfs algorithm to try to accomplish this. I have tried running the code on smaller inputs and it works but when the input size increases, it returns the wrong answer. I have tried using other algorithms i.e. Trajan's algorithm but even that has not worked for me.

A sample input file:

6 5 5
1 2
2 3
3 1
4 5
5 6

The first 3 numbers represent total vertices, total edges, starting vertex
and next line represent the edges (the first number is v1 and the second v2).

The code work fine for this but not for larger inputs. I dont seem to understand where the problem is!

https://file.io/bHnJHoqSE3ji contains the input text file. The output the algo is giving is 356 and the expected output is 263.

答案1

得分: 2

首先,似乎你的邻接表是以1为基础,而你的访问数组是以0为基础,有时你使用你的邻接表就好像它是以0为基础的。

其次,我注意到你根本没有使用变量“start”。然而,如果图看起来像这样:

2 <- 1

如果起始节点是2,那么答案是1。如果起始节点是1,那么答案是0。如果你的代码中没有使用“start”,那么你的算法几乎不可能正确。

英文:

First, it seems that your adjacency list is 1-based while your visit
array is 0-based, and you sometimes use your adjacency list as if it's 0-based.

Second, I noticed that you didn't use the variable start at all. However, what if the graph looks like this:

2 <- 1

If the start node is 2, then the answer is 1. If the start node is 1 then the answer is 0. If you didn't use start in your code, it's impossible that your algorithm is correct.

答案2

得分: 0

如@TYeung所指出,你忽略了使用起始顶点。如果你从指定的顶点开始,将会获得更好的结果:

int findMinEdges(Graph& graph, int start) {
    int num_vertices = graph.getVertices();
    vector<bool> visited(num_vertices, false);
    dfs(graph, start, visited);
    int edges = 0;
    for (int i = 0; i < num_vertices; i++) {
        if (!visited[i]) {
            dfs(graph, i, visited);
            edges++;
        }
    }
    return (edges - 1);
}

然而,是否获得最小数量的边取决于输入顶点的顺序。

考虑这个图:

0 -> 1
2 -> 1
3 -> 1
3 -> 2
DFS起始点 未访问的顶点 边数
0 2,3 0
2 3 1
3 - 2

现在以不同的顺序输入顶点:

0 -> 1
3 -> 1
3 -> 2
2 -> 1
DFS起始点 未访问的顶点 边数
0 2,3 0
3 - 1
英文:

As @TYeung points out, you have missed using the start vertex. You will get better result if you do start from the specified vertex:

int findMinEdges(Graph&amp; graph, int start) {
int num_vertices = graph.getVertices();
vector&lt;bool&gt; visited(num_vertices, false);
dfs(graph, start, visited);
int edges = 0;
for (int i = 0; i &lt; num_vertices; i++) {
if (!visited[i]) {
dfs(graph, i, visited);
edges++;
}
}
return (edges - 1);
}

However, whether or not you get the minimum number of edges depends on the order of the input vertices.

Consider this graph

0 -&gt; 1
2 -&gt; 1
3 -&gt; 1
3 -&gt; 2
DFS start unvisited edges
0 2,3 0
2 3 1
3 - 2

Now input the vertices in a different order

0 -&gt; 1
3 -&gt; 1
3 -&gt; 2
2 -&gt; 1
DFS start unvisited edges
0 2,3 0
3 - 1

huangapple
  • 本文由 发表于 2023年5月28日 20:17:30
  • 转载请务必保留本文链接:https://go.coder-hub.com/76351448.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定