📌  相关文章
📜  要在有向图中添加的最小边,以便可以从给定节点访问任何节点

📅  最后修改于: 2021-04-26 10:52:26             🧑  作者: Mango

给定一个有向图和一个节点X。任务是找到必须添加到图中的最小边数,以便可以从给定节点访问任何节点。
例子:

方法:首先,让我们使用简单的DFS将X可以到达的所有顶点标记为良好。然后,对于每个坏顶点(无法从X到达的顶点)v,计算从v可以到达的坏顶点的数量(也可以通过简单的DFS完成)。将此数字设为cnt v 。现在,以cnt v的非递增顺序遍历所有坏顶点。对于当前的不良顶点v,如果仍未将其标记为好,请从该顶点运行DFS,将所有可到达的顶点标记为好,然后将答案增加1(实际上,我们隐含地添加了边(s,v ))。可以证明,该解决方案给出了最佳答案。
下面是上述方法的实现:

C++
// C++ implementation of the approach
 
#include 
using namespace std;
 
const int N = 5010;
 
int n, x;
 
vector g[N];
 
// To check if the vertex has been
// visited or not
bool vis[N];
 
// To store if vertex is reachable
// from source or not
bool good[N];
 
int cnt;
 
void ADD_EDGE(int u, int v)
{
    g[u].push_back(v);
}
 
// Function to find all good vertices
void dfs1(int v)
{
    good[v] = true;
    for (auto to : g[v])
        if (!good[to])
            dfs1(to);
}
 
// Function to find cnt of all unreachable vertices
void dfs2(int v)
{
    vis[v] = true;
    ++cnt;
    for (auto to : g[v])
        if (!vis[to] && !good[to])
            dfs2(to);
}
 
// Function to return the minimum edges required
int Minimum_Edges()
{
 
    // Find all vertices reachable from the source
    dfs1(x);
 
    // To store all vertices with their cnt value
    vector > val;
 
    for (int i = 0; i < n; ++i) {
 
        // If vertex is bad i.e. not reachable
        if (!good[i]) {
            cnt = 0;
            memset(vis, false, sizeof(vis));
 
            // Find cnt of this vertex
            dfs2(i);
            val.push_back(make_pair(cnt, i));
        }
    }
 
    // Sort all unreachable vertices in
    // non-decreasing order of their cnt values
    sort(val.begin(), val.end());
    reverse(val.begin(), val.end());
 
    // Find the minimum number of edges
    // needed to be added
    int ans = 0;
    for (auto it : val) {
        if (!good[it.second]) {
            ++ans;
            dfs1(it.second);
        }
    }
 
    return ans;
}
 
// Driver code
int main()
{
    // Number of nodes and source node
    n = 5, x = 4;
 
    // Add edges to the graph
    ADD_EDGE(0, 1);
    ADD_EDGE(1, 2);
    ADD_EDGE(2, 3);
    ADD_EDGE(3, 0);
 
    cout << Minimum_Edges();
 
    return 0;
}


Java
// Java implementation of the approach
import java.util.*;
 
class GFG
{
     
// pair
static class pair
{
    int first,second;
    pair(int a,int b)
    {
        first = a;
        second = b;
    }
}
 
static int N = 5010;
 
static int n, x;
 
static Vector> g = new Vector>();
 
// To check if the vertex has been
// visited or not
static boolean vis[] = new boolean[N];
 
// To store if vertex is reachable
// from source or not
static boolean good[] = new boolean[N];
 
static int cnt;
 
static void ADD_EDGE(int u, int v)
{
    g.get(u).add(v);
}
 
// Function to find all good vertices
static void dfs1(int v)
{
    good[v] = true;
    for (int to = 0; to < g.get(v).size(); to++)
        if (!good[g.get(v).get(to)])
            dfs1(g.get(v).get(to));
}
 
// Function to find cnt of all unreachable vertices
static void dfs2(int v)
{
    vis[v] = true;
    ++cnt;
    for (int to = 0; to < g.get(v).size(); to++)
        if (!vis[g.get(v).get(to)] && !good[g.get(v).get(to)])
            dfs2(g.get(v).get(to));
}
 
// Function to return the minimum edges required
static int Minimum_Edges()
{
 
    // Find all vertices reachable from the source
    dfs1(x);
 
    // To store all vertices with their cnt value
    Vector val = new Vector();
 
    for (int i = 0; i < n; ++i)
    {
 
        // If vertex is bad i.e. not reachable
        if (!good[i])
        {
            cnt = 0;
            for(int j = 0; j < vis.length; j++)
                vis[j] = false;
 
            // Find cnt of this vertex
            dfs2(i);
            val.add(new pair(cnt, i));
        }
    }
 
    // Sort all unreachable vertices in
    // non-decreasing order of their cnt values
    Collections.sort(val,new Comparator()
    {
            public int compare(pair p1, pair p2)
            {
                return p1.first - p2.first;
            }
    });
         
    Collections.reverse(val);
 
    // Find the minimum number of edges
    // needed to be added
    int ans = 0;
    for (int it = 0; it < val.size(); it++)
    {
        if (!good[val.get(it).second])
        {
            ++ans;
            dfs1(val.get(it).second);
        }
    }
 
    return ans;
}
 
// Driver code
public static void main(String args[])
{
    // Number of nodes and source node
    n = 5; x = 4;
     
    for(int i = 0; i < N + 1; i++)
    g.add(new Vector());
 
    // Add edges to the graph
    ADD_EDGE(0, 1);
    ADD_EDGE(1, 2);
    ADD_EDGE(2, 3);
    ADD_EDGE(3, 0);
 
    System.out.println( Minimum_Edges());
}
}
 
// This code is contributed by Arnab Kundu


Python3
# Python3 implementation of the approach
N = 5010
g = [[] for i in range(N)]
 
# To check if the vertex
# has been visited or not
vis = [False for i in range(N)]
 
# To store if vertex is reachable
# from source or not
good = [False for i in range(N)]
 
def ADD_EDGE(u, v):
 
    g[u].append(v)
 
# Function to find all good vertices
def dfs1(v):
 
    good[v] = True
    for to in g[v]:
        if not good[to]:
            dfs1(to)
 
# Function to find cnt of
# all unreachable vertices
def dfs2(v):
     
    global cnt
    vis[v] = True
    cnt += 1
    for to in g[v]:
        if not vis[to] and not good[to]:
            dfs2(to)
 
# Function to return 
# the minimum edges required
def Minimum_Edges():
 
    global vis, cnt
     
    # Find all vertices reachable
    # from the source
    dfs1(x)
 
    # To store all vertices
    # with their cnt value
    val = []
 
    for i in range(0, n):
 
        # If vertex is bad i.e. not reachable
        if not good[i]:
            cnt = 0
            vis = [False for i in range(N)]
 
            # Find cnt of this vertex
            dfs2(i)
            val.append((cnt, i))
 
    # Sort all unreachable vertices
    # in non-decreasing order of
    # their cnt values
    val.sort(reverse = True)
 
    # Find the minimum number of edges
    # needed to be added
    ans = 0
    for it in val:
        if not good[it[1]]:
            ans += 1
            dfs1(it[1])
 
    return ans
 
# Driver code
if __name__ == "__main__":
 
    # Number of nodes and source node
    n, x = 5, 4
 
    # Add edges to the graph
    ADD_EDGE(0, 1)
    ADD_EDGE(1, 2)
    ADD_EDGE(2, 3)
    ADD_EDGE(3, 0)
 
    print(Minimum_Edges())
 
# This code is contributed by Rituraj Jain


C#
// C# implementation of the approach
using System;
using System.Collections;
using System.Collections.Generic;
  
class GFG
{
      
// pair
class pair
{
    public int first,second;
    public pair(int a,int b)
    {
        first = a;
        second = b;
    }
}
  
static int N = 5010;
  
static int n, x;
  
static ArrayList g = new ArrayList();
  
// To check if the vertex has been
// visited or not
static bool []vis = new bool[N];
  
// To store if vertex is reachable
// from source or not
static bool []good = new bool[N];
  
static int cnt;
  
static void Add_EDGE(int u, int v)
{
    ((ArrayList)g[u]).Add(v);
}
  
// Function to find all good vertices
static void dfs1(int v)
{
    good[v] = true;
    for (int to = 0; to < ((ArrayList)g[v]).Count; to++)
        if (!good[(int)((ArrayList)g[v])[to]])
            dfs1((int)((ArrayList)g[v])[to]);
}
  
// Function to find cnt of all unreachable vertices
static void dfs2(int v)
{
    vis[v] = true;
    ++cnt;
    for (int to = 0; to < ((ArrayList)g[v]).Count; to++)
        if (!vis[(int)((ArrayList)g[v])[to]] && !good[(int)((ArrayList)g[v])[to]])
            dfs2((int)((ArrayList)g[v])[to]);
}
 
class sortHelper : IComparer
{
   int IComparer.Compare(object a, object b)
   {
      pair first = (pair)a;
      pair second = (pair)b;
         
      return first.first - second.first;
   }
}
  
// Function to return the minimum edges required
static int Minimum_Edges()
{
  
    // Find all vertices reachable from the source
    dfs1(x);
  
    // To store all vertices with their cnt value
    ArrayList val = new ArrayList();
  
    for (int i = 0; i < n; ++i)
    {
  
        // If vertex is bad i.e. not reachable
        if (!good[i])
        {
            cnt = 0;
            for(int j = 0; j < vis.Length; j++)
                vis[j] = false;
  
            // Find cnt of this vertex
            dfs2(i);
            val.Add(new pair(cnt, i));
        }
    }
  
    // Sort all unreachable vertices in
    // non-decreasing order of their cnt values
    val.Sort(new sortHelper());
  
    // Find the minimum number of edges
    // needed to be Added
    int ans = 0;
    for (int it = 0; it < val.Count; it++)
    {
        if (!good[((pair)val[it]).second])
        {
            ++ans;
            dfs1(((pair)val[it]).second);
        }
    }
  
    return ans;
}
  
// Driver code
public static void Main(string []args)
{
    // Number of nodes and source node
    n = 5; x = 4;
      
    for(int i = 0; i < N + 1; i++)
        g.Add(new ArrayList());
  
    // Add edges to the graph
    Add_EDGE(0, 1);
    Add_EDGE(1, 2);
    Add_EDGE(2, 3);
    Add_EDGE(3, 0);
  
    Console.WriteLine(Minimum_Edges());
}
}
 
// This code is contributed by rutvik_56


输出:
1