📌  相关文章
📜  在给定的二叉树中找到最大匹配

📅  最后修改于: 2021-04-22 02:10:45             🧑  作者: Mango

给定一棵具有N个节点的树,其值从1到N,并且N – 1个边。任务是在给定的树中找到最大的匹配项。

例子:

方法:可以使用贪婪方法解决此问题,其思想是在树中使用后顺序遍历,并从叶边缘开始并按顺序进行。步骤如下:

  1. 在根节点为1的给定树上执行DFS遍历,并将父节点设为0,并在递归DFS遍历中将当前节点作为该节点的父节点传递。
  2. 在执行遍历时,对于每个节点U及其父节点P(如果未访问这些节点),则将这些节点标记为已访问,并将最大匹配计数增加1。
  3. 在“ DFS遍历”之后,在上述步骤中打印最大匹配数。

贪婪算法是要反复获取任何叶子边缘。

TreeMatch(F:forest)
M <- []
while F nonempty do {
     select any leaf-edge e
     M <- M + [e]
     F <- F - both ends of e
  }


为什么贪心算法可以正常工作?
让我们假设E是叶边缘,并考虑任何最大匹配N。假设N不包含E。然后,如果我们将E添加到N ,则现在只有一个顶点具有两个入射的边。因此,我们可以删除N的边之一,并获得包含E的最大匹配。

下面是上述方法的实现:

C++
// C++ program for the above approach
#include 
using namespace std;
#define N 10000
 
// Adjacency list to store edges
vector adj[N];
 
int used[N];
int max_matching;
 
// Add an edge between U and V in tree
void AddEdge(int u, int v)
{
    // Edge from u to v
    adj[u].push_back(v);
 
    // Edge from V to U
    adj[v].push_back(u);
}
 
// Function that finds the maximum
// matching of the DFS
void Matching_dfs(int u, int p)
{
    for (int i = 0;
         i < adj[u].size(); i++) {
 
        // Go further as we are not
        // allowed to go towards
        // its parent
        if (adj[u][i] != p) {
            Matching_dfs(adj[u][i], u);
        }
    }
 
    // If U and its parent P is
    // not taken then we must
    // take &mark them as taken
    if (!used[u] and !used[p] and p != 0) {
 
        // Increment size of edge set
        max_matching++;
        used[u] = used[p] = 1;
    }
}
 
// Function to find the maximum
// matching in a graph
void maxMatching()
{
    // Taking 1 as a root of the tree
    Matching_dfs(1, 0);
 
    // Print maximum Matching
    cout << max_matching << "\n";
}
 
// Driver Code
int main()
{
    int n = 5;
 
    // Joining edge between
    // two nodes in tree
    AddEdge(1, 2);
    AddEdge(1, 3);
    AddEdge(3, 4);
    AddEdge(3, 5);
 
    // Function Call
    maxMatching();
    return 0;
}


Java
// Java program for the above approach
import java.util.*;
 
class GFG{
     
static final int N = 10000;
 
// Adjacency list to store edges
@SuppressWarnings("unchecked")
static Vector[] adj = new Vector[N];
 
static int used[] = new int[N];
static int max_matching;
 
// Add an edge between U and V in tree
static void AddEdge(int u, int v)
{
     
    // Edge from u to v
    adj[u].add(v);
 
    // Edge from V to U
    adj[v].add(u);
}
 
// Function that finds the maximum
// matching of the DFS
static void Matching_dfs(int u, int p)
{
    for(int i = 0; i < adj[u].size(); i++)
    {
         
        // Go further as we are not
        // allowed to go towards
        // its parent
        if (adj[u].get(i) != p)
        {
            Matching_dfs(adj[u].get(i), u);
        }
    }
 
    // If U and its parent P is
    // not taken then we must
    // take &mark them as taken
    if (used[u] == 0 &&
        used[p] == 0 && p != 0)
    {
         
        // Increment size of edge set
        max_matching++;
        used[u] = used[p] = 1;
    }
}
 
// Function to find the maximum
// matching in a graph
static void maxMatching()
{
     
    // Taking 1 as a root of the tree
    Matching_dfs(1, 0);
 
    // Print maximum Matching
    System.out.print(max_matching + "\n");
}
 
// Driver Code
public static void main(String[] args)
{
    for(int i = 0; i < adj.length; i++)
        adj[i] = new Vector();
         
    // Joining edge between
    // two nodes in tree
    AddEdge(1, 2);
    AddEdge(1, 3);
    AddEdge(3, 4);
    AddEdge(3, 5);
 
    // Function call
    maxMatching();
}
}
 
// This code is contributed by amal kumar choubey


Python3
# Python3 program for the above approach
N = 10000
 
# Adjacency list to store edges
adj = {}
 
used = [0 for i in range(N)]
 
max_matching = 0
 
# Add an edge between U and V in tree
def AddEdge(u, v):
     
    if u not in adj:
        adj[u] = []
    if v not in adj:
        adj[v] = []
 
    # Edge from u to v
    adj[u].append(v)
 
    # Edge from V to U
    adj[v].append(u)
 
# Function that finds the maximum
# matching of the DFS
def Matching_dfs(u, p):
     
    global max_matching
     
    for i in range(len(adj[u])):
 
        # Go further as we are not
        # allowed to go towards
        # its parent
        if (adj[u][i] != p):
            Matching_dfs(adj[u][i], u)
 
    # If U and its parent P is
    # not taken then we must
    # take &mark them as taken
    if (not used[u] and not used[p] and p != 0):
         
        # Increment size of edge set
        max_matching += 1
        used[u] = 1
        used[p] = 1
 
# Function to find the maximum
# matching in a graph
def maxMatching():
 
    # Taking 1 as a root of the tree
    Matching_dfs(1, 0)
 
    # Print maximum Matching
    print(max_matching)
     
# Driver Code
n = 5
 
# Joining edge between
# two nodes in tree
AddEdge(1, 2)
AddEdge(1, 3)
AddEdge(3, 4)
AddEdge(3, 5)
 
# Function Call
maxMatching()
 
# This code is contributed by avanitrachhadiya2155


C#
// C# program for the above approach
using System;
using System.Collections.Generic;
 
class GFG{
     
static readonly int N = 10000;
 
// Adjacency list to store edges
static List[] adj = new List[N];
 
static int []used = new int[N];
static int max_matching;
 
// Add an edge between U and V in tree
static void AddEdge(int u, int v)
{
     
    // Edge from u to v
    adj[u].Add(v);
 
    // Edge from V to U
    adj[v].Add(u);
}
 
// Function that finds the maximum
// matching of the DFS
static void Matching_dfs(int u, int p)
{
    for(int i = 0; i < adj[u].Count; i++)
    {
         
        // Go further as we are not
        // allowed to go towards
        // its parent
        if (adj[u][i] != p)
        {
            Matching_dfs(adj[u][i], u);
        }
    }
 
    // If U and its parent P is
    // not taken then we must
    // take &mark them as taken
    if (used[u] == 0 &&
        used[p] == 0 && p != 0)
    {
         
        // Increment size of edge set
        max_matching++;
        used[u] = used[p] = 1;
    }
}
 
// Function to find the maximum
// matching in a graph
static void maxMatching()
{
     
    // Taking 1 as a root of the tree
    Matching_dfs(1, 0);
 
    // Print maximum Matching
    Console.Write(max_matching + "\n");
}
 
// Driver Code
public static void Main(String[] args)
{
    for(int i = 0; i < adj.Length; i++)
        adj[i] = new List();
         
    // Joining edge between
    // two nodes in tree
    AddEdge(1, 2);
    AddEdge(1, 3);
    AddEdge(3, 4);
    AddEdge(3, 5);
 
    // Function call
    maxMatching();
}
}
 
// This code is contributed by amal kumar choubey


输出:
2


时间复杂度: O(V + E),其中V是边的数量,E是边的数量。
辅助空间: O(V)