📜  给定图的路径中的最大桥数

📅  最后修改于: 2021-10-25 03:24:31             🧑  作者: Mango

给定一个无向图,任务是计算给定图中任意两个顶点之间的桥的最大数量。
例子:

Input: 
Graph
1 ------- 2 ------- 3 -------- 4
          |         |
          |         |
          5 ------- 6
Output: 2 
Explanation: 
There are 2 bridges, (1 - 2)
and (3 - 4), in the path from 1 to 4.

Input: 
Graph:
1 ------- 2 ------- 3 ------- 4
Output: 3 
Explanation: 
There are 3 bridges, (1 - 2), (2 - 3)
and (3 - 4) in the path from 1 to 4.

方法:
请按照以下步骤解决问题:

  • 找到图中的所有桥并将它们存储在一个向量中。
  • 移除所有桥接将图形缩减为小组件。
  • 这些小组件没有任何桥接,它们是不包含桥接的弱连接组件。
  • 生成由桥连接的节点组成的树,以桥为边。
  • 现在,任何节点之间的路径中的最大桥梁等于这棵树的直径。
  • 因此,找到这棵树的直径并将其打印为答案。

下面是上述方法的实现

C++
// C++ program to find the
// maximum number of bridges
// in any path of the given graph
 
#include 
using namespace std;
 
const int N = 1e5 + 5;
 
// Stores the nodes
// and their connections
vector > v(N);
 
// Store the tree with
// Bridges as the edges
vector > g(N);
 
// Stores the visited nodes
vector vis(N, 0);
 
// for finding bridges
vector in(N), low(N);
 
// for Disjoint Set Union
vector parent(N), rnk(N);
// for storing actaul bridges
vector > bridges;
 
// Stores the number of
// nodes and edges
int n, m;
// For finding bridges
int timer = 0;
 
int find_set(int a)
{
    // Function to find root of
    // the component in which
    // A lies
    if (parent[a] == a)
        return a;
 
    // Doing path compression
    return parent[a]
           = find_set(parent[a]);
}
 
void union_set(int a, int b)
{
    // Function to do union
    // between a and b
    int x = find_set(a), y = find_set(b);
 
    // If both are already in the
    // same component
    if (x == y)
        return;
 
    // If both have same rank,
    // then increase anyone's rank
    if (rnk[x] == rnk[y])
        rnk[x]++;
 
    if (rnk[y] > rnk[x])
        swap(x, y);
 
    parent[y] = x;
}
 
// Function to find bridges
void dfsBridges(int a, int par)
{
    vis[a] = 1;
    // Initialize in time and
    // low value
    in[a] = low[a] = timer++;
 
    for (int i v[a]) {
 
        if (i == par)
            continue;
 
        if (vis[i])
 
            // Update the low value
            // of the parent
            low[a] = min(low[a], in[i]);
        else {
 
            // Perform DFS on its child
            // updating low if the child
            // has connection with any
            // ancestor
            dfsBridges(i, a);
 
            low[a] = min(low[a], low[i]);
 
            if (in[a] < low[i])
 
                // Bridge found
                bridges.push_back(make_pair(i, a));
 
            // Otherwise
            else
 
                // Find union between parent
                // and child as they
                // are in same component
                union_set(i, a);
        }
    }
}
 
// Function to find diameter of the
// tree for storing max two depth child
int dfsDiameter(int a, int par, int& diameter)
{
    int x = 0, y = 0;
    for (int i g[a]) {
        if (i == par)
            continue;
 
        int mx = dfsDiameter(i, a, diameter);
 
        // Finding max two depth
        // from its children
        if (mx > x) {
            y = x;
            x = mx;
        }
        else if (mx > y)
            y = mx;
    }
 
    // Update diameter with the
    // sum of max two depths
    diameter = max(diameter, x + y);
 
    // Return the maximum depth
    return x + 1;
}
 
// Function to find maximum
// bridges bwtween
// any two nodes
int findMaxBridges()
{
 
    for (int i = 0; i <= n; i++) {
        parent[i] = i;
        rnk[i] = 1;
    }
 
    // DFS to find bridges
    dfsBridges(1, 0);
 
    // If no bridges are found
    if (bridges.empty())
        return 0;
 
    int head = -1;
 
    // Iterate over all bridges
    for (auto& i bridges) {
 
        // Find the endpoints
        int a = find_set(i.first);
        int b = find_set(i.second);
 
        // Generate the tree with
        // bridges as the edges
        g[a].push_back(b);
        g[b].push_back(a);
 
        // Update the head
        head = a;
    }
 
    int diameter = 0;
    dfsDiameter(head, 0, diameter);
 
    // Return the diameter
    return diameter;
}
 
// Driver Code
int main()
{
    /*
     
    Graph =>
 
        1 ---- 2 ---- 3 ---- 4
               |      |
               5 ---- 6
    */
 
    n = 6, m = 6;
 
    v[1].push_back(2);
    v[2].push_back(1);
    v[2].push_back(3);
    v[3].push_back(2);
    v[2].push_back(5);
    v[5].push_back(2);
    v[5].push_back(6);
    v[6].push_back(5);
    v[6].push_back(3);
    v[3].push_back(6);
    v[3].push_back(4);
    v[4].push_back(4);
 
    int ans = findMaxBridges();
 
    cout << ans << endl;
 
    return 0;
}


Java
// Java program to find the
// maximum number of bridges
// in any path of the given graph
import java.util.*;
class GFG{
 
static int N = (int)1e5 + 5;
 
// Stores the nodes
// and their connections
static Vector []v =
       new Vector[N];
 
// Store the tree with
// Bridges as the edges
static Vector []g =
       new Vector[N];
 
// Stores the visited nodes
static boolean []vis =
       new boolean[N];
 
// For finding bridges
static int []in = new int[N];
static int []low = new int[N];
 
// for Disjoint Set Union
static int []parent = new int[N];
static int []rnk = new int[N];
   
// For storing actaul bridges
static Vector bridges =
       new Vector<>();
 
// Stores the number of
// nodes and edges
static int n, m;
   
// For finding bridges
static int timer = 0;
static int diameter;
   
static class pair
{
  int first, second;
  public pair(int first,
              int second) 
  {
    this.first = first;
    this.second = second;
  }   
}
 
static void swap(int x,
                 int y)
{
  int temp = x;
  x = y;
  y = temp;
}
 
static int find_set(int a)
{
  // Function to find root of
  // the component in which
  // A lies
  if (parent[a] == a)
    return a;
 
  // Doing path compression
  return parent[a] =
         find_set(parent[a]);
}
 
static void union_set(int a, int b)
{
  // Function to do union
  // between a and b
  int x = find_set(a),
      y = find_set(b);
 
  // If both are already
  // in the same component
  if (x == y)
    return;
 
  // If both have same rank,
  // then increase anyone's rank
  if (rnk[x] == rnk[y])
    rnk[x]++;
 
  if (rnk[y] > rnk[x])
    swap(x, y);
 
  parent[y] = x;
}
 
// Function to find bridges
static void dfsBridges(int a,
                       int par)
{
  vis[a] = true;
   
  // Initialize in time and
  // low value
  in[a] = low[a] = timer++;
 
  for (int i : v[a])
  {
    if (i == par)
      continue;
 
    if (vis[i])
 
      // Update the low value
      // of the parent
      low[a] = Math.min(low[a],
                        in[i]);
    else
    {
      // Perform DFS on its child
      // updating low if the child
      // has connection with any
      // ancestor
      dfsBridges(i, a);
 
      low[a] = Math.min(low[a],
                        low[i]);
 
      if (in[a] < low[i])
 
        // Bridge found
        bridges.add(new pair(i, a));
 
      // Otherwise
      else
 
        // Find union between parent
        // and child as they
        // are in same component
        union_set(i, a);
    }
  }
}
 
// Function to find diameter
// of the tree for storing
// max two depth child
static int dfsDiameter(int a,
                       int par)
{
  int x = 0, y = 0;
  for (int i : g[a])
  {
    if (i == par)
      continue;
 
    int mx = dfsDiameter(i, a);
 
    // Finding max two depth
    // from its children
    if (mx > x)
    {
      y = x;
      x = mx;
    }
    else if (mx > y)
      y = mx;
  }
 
  // Update diameter with the
  // sum of max two depths
  diameter = Math.max(diameter,
                      x + y);
 
  // Return the maximum depth
  return x + 1;
}
 
// Function to find maximum
// bridges bwtween
// any two nodes
static int findMaxBridges()
{
  for (int i = 0; i <= n; i++)
  {
    parent[i] = i;
    rnk[i] = 1;
  }
 
  // DFS to find bridges
  dfsBridges(1, 0);
 
  // If no bridges are found
  if (bridges.isEmpty())
    return 0;
 
  int head = -1;
 
  // Iterate over all bridges
  for (pair i : bridges)
  {
    // Find the endpoints
    int a = find_set(i.first);
    int b = find_set(i.second);
 
    // Generate the tree with
    // bridges as the edges
    g[a].add(b);
    g[b].add(a);
 
    // Update the head
    head = a;
  }
 
  diameter = 0;
  dfsDiameter(head, 0);
 
  // Return the diameter
  return diameter;
}
 
// Driver Code
public static void main(String[] args)
{
  /*
 
    Graph =>
 
        1 ---- 2 ---- 3 ---- 4
               |      |
               5 ---- 6
    */
 
  n = 6;
  m = 6;
   
  for (int i = 0; i < v.length; i++)
    v[i] = new Vector();
 
  for (int i = 0; i < g.length; i++)
    g[i] = new Vector();
   
  v[1].add(2);
  v[2].add(1);
  v[2].add(3);
  v[3].add(2);
  v[2].add(5);
  v[5].add(2);
  v[5].add(6);
  v[6].add(5);
  v[6].add(3);
  v[3].add(6);
  v[3].add(4);
  v[4].add(4);
 
  int ans = findMaxBridges();
  System.out.print(ans + "\n");
}
}
 
// This code is contributed by Princi Singh


C#
// C# program to find the
// maximum number of bridges
// in any path of the given graph
using System;
using System.Collections.Generic;
class GFG{
 
static int N = (int)1e5 + 5;
 
// Stores the nodes
// and their connections
static List []v =
       new List[N];
 
// Store the tree with
// Bridges as the edges
static List []g =
       new List[N];
 
// Stores the visited nodes
static bool []vis =
       new bool[N];
 
// For finding bridges
static int []init = new int[N];
static int []low = new int[N];
 
// for Disjoint Set Union
static int []parent = new int[N];
static int []rnk = new int[N];
   
// For storing actaul bridges
static List bridges =
       new List();
 
// Stores the number of
// nodes and edges
static int n, m;
   
// For finding bridges
static int timer = 0;
static int diameter;
   
class pair
{
  public int first, second;
  public pair(int first,
              int second) 
  {
    this.first = first;
    this.second = second;
  }   
}
 
static void swap(int x,
                 int y)
{
  int temp = x;
  x = y;
  y = temp;
}
 
static int find_set(int a)
{
  // Function to find root of
  // the component in which
  // A lies
  if (parent[a] == a)
    return a;
 
  // Doing path compression
  return parent[a] =
         find_set(parent[a]);
}
 
static void union_set(int a,
                      int b)
{
  // Function to do union
  // between a and b
  int x = find_set(a),
      y = find_set(b);
 
  // If both are already
  // in the same component
  if (x == y)
    return;
 
  // If both have same rank,
  // then increase anyone's rank
  if (rnk[x] == rnk[y])
    rnk[x]++;
 
  if (rnk[y] > rnk[x])
    swap(x, y);
 
  parent[y] = x;
}
 
// Function to find bridges
static void dfsBridges(int a,
                       int par)
{
  vis[a] = true;
   
  // Initialize in time and
  // low value
  init[a] = low[a] = timer++;
 
  foreach (int i in v[a])
  {
    if (i == par)
      continue;
 
    if (vis[i])
 
      // Update the low value
      // of the parent
      low[a] = Math.Min(low[a],
                        init[i]);
    else
    {
      // Perform DFS on its child
      // updating low if the child
      // has connection with any
      // ancestor
      dfsBridges(i, a);
 
      low[a] = Math.Min(low[a],
                        low[i]);
 
      if (init[a] < low[i])
 
        // Bridge found
        bridges.Add(new pair(i, a));
 
      // Otherwise
      else
 
        // Find union between parent
        // and child as they
        // are in same component
        union_set(i, a);
    }
  }
}
 
// Function to find diameter
// of the tree for storing
// max two depth child
static int dfsDiameter(int a,
                       int par)
{
  int x = 0, y = 0;
  foreach (int i in g[a])
  {
    if (i == par)
      continue;
 
    int mx = dfsDiameter(i, a);
 
    // Finding max two depth
    // from its children
    if (mx > x)
    {
      y = x;
      x = mx;
    }
    else if (mx > y)
      y = mx;
  }
 
  // Update diameter with the
  // sum of max two depths
  diameter = Math.Max(diameter,
                      x + y);
 
  // Return the
  // maximum depth
  return x + 1;
}
 
// Function to find maximum
// bridges bwtween
// any two nodes
static int findMaxBridges()
{
  for (int i = 0; i <= n; i++)
  {
    parent[i] = i;
    rnk[i] = 1;
  }
 
  // DFS to find bridges
  dfsBridges(1, 0);
 
  // If no bridges are found
  if (bridges.Count == 0)
    return 0;
 
  int head = -1;
 
  // Iterate over all bridges
  foreach (pair i in bridges)
  {
    // Find the endpoints
    int a = find_set(i.first);
    int b = find_set(i.second);
 
    // Generate the tree with
    // bridges as the edges
    g[a].Add(b);
    g[b].Add(a);
 
    // Update the head
    head = a;
  }
 
  diameter = 0;
  dfsDiameter(head, 0);
 
  // Return the diameter
  return diameter;
}
 
// Driver Code
public static void Main(String[] args)
{
  /*
 
    Graph =>
 
        1 ---- 2 ---- 3 ---- 4
               |      |
               5 ---- 6
    */
 
  n = 6;
  m = 6;
   
  for (int i = 0; i < v.Length; i++)
    v[i] = new List();
 
  for (int i = 0; i < g.Length; i++)
    g[i] = new List();
   
  v[1].Add(2);
  v[2].Add(1);
  v[2].Add(3);
  v[3].Add(2);
  v[2].Add(5);
  v[5].Add(2);
  v[5].Add(6);
  v[6].Add(5);
  v[6].Add(3);
  v[3].Add(6);
  v[3].Add(4);
  v[4].Add(4);
 
  int ans = findMaxBridges();
  Console.Write(ans + "\n");
}
}
 
// This code is contributed by Amit Katiyar


Javascript


输出:
2

时间复杂度: O(N + M)
辅助空间: O(N + M)