📌  相关文章
📜  由至少一个黑边组成的长度为 K 的节点序列的计数

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

给定一棵树,由N 个节点组成,从[1, N]编号颜色为黑色(用 1 表示)绿色(用 0 表示) ,任务是计算长度为K [a 1 , a 2 , ..a K ] 使得在连续节点之间采取的路径是最短的,并且覆盖的边由至少一个黑色边组成。由于答案可能很大,请将其打印为10 9 +7 的模数。

方法:
这个想法是计算长度为K的序列的数量,使得没有黑边被覆盖。让计数为temp 。那么(N K ) – temp是必需的答案。通过去除黑边,然后计算结果图的不同组件的大小,可以轻松计算temp

请按照以下步骤操作:

  1. ans的值初始化为N K
  2. 通过仅添加绿色边构建图G。
  3. 对图执行 DFS 遍历并不断从ans中减去(大小K ,其中大小是图 G 的不同组件中的节点数。

下面是上述方法的实现:

C++
// C++ implementation of the
// above approach
#include 
#define int long long int
using namespace std;
 
const int mod = 1e9 + 7;
const int N = 1e5 + 1;
 
// Vector to store the graph
vector G[N];
 
// Iterative Function to calculate
// (ab) % mod in O(log b)
int power(int a, int b) {
 
    // Initialize result
    int res = 1;
 
    // Update x if it is more than
    // or equal to p
    a = a % mod;
    if (a == 0)
 
      // In case x is divisible by p;
      return 0;
 
    while (b > 0) {
 
        // If a is odd,
        // multiply x with result
        if (b & 1)
            res = (res * a) % mod;
 
        // b must be even now
        b = b >> 1; // b = b/2
        a = (a * a) % mod;
    }
    return res;
}
 
// DFS traversal of the nodes
void dfs(int i, int& size,
         bool* visited) {
     
    // Mark the current
    // node as visited
    visited[i] = true;
     
    // Increment  the size of the
    // current component
    size++;
 
    // Recur for all the vertices
    // adjacent to this node
    for (auto nbr : G[i]) {
        if (!visited[nbr]) {
          dfs(nbr, size, visited);
        }
    }
}
 
// Function to calculate the
// final answer
void totalSequences(int& ans,
                    int n, int k)
{
    // Mark all the vertices as
    // not visited initially
    bool visited[n + 1];
    memset(visited, false,
           sizeof(visited));
 
  // Subtract (size^k) from the answer
  // for different components
    for (int i = 1; i <= n; i++) {
        if (!visited[i]) {
            int size = 0;
            dfs(i, size, visited);
            ans -= power(size, k);
            ans += mod;
            ans = ans % mod;
        }
    }
}
 
// Function to add edges to the graph
void addEdge(int x, int y, int color)
{
    // If the colour is green,
    // include it in the graph
    if (color == 0) {
        G[x].push_back(y);
        G[y].push_back(x);
    }
}
int32_t main()
{
    // Number of node in the tree
    int n = 3;
 
    // Size of sequence
    int k = 3;
 
    // Initialize the result as n^k
    int ans = power(n, k);
    /* 2
     /   \
    1     3
        
   Let us create binary tree as shown
   in above example */
    addEdge(1, 2, 1);
    addEdge(2, 3, 1);
 
    totalSequences(ans, n, k);
    cout << ans << endl;
}


Java
// Java implementation of the
// above approach
import java.util.*;
 
class GFG{
 
static int mod = (int)(1e9 + 7);
static int N = (int)(1e5 + 1);
static  int size;
static int ans;
 
// Vector to store the graph
@SuppressWarnings("unchecked")
static Vector []G = new Vector[N];
 
// Iterative Function to calculate
// (ab) % mod in O(log b)
static int power(int a, int b)
{
     
    // Initialize result
    int res = 1;
 
    // Update x if it is more than
    // or equal to p
    a = a % mod;
     
    if (a == 0)
     
        // In case x is divisible by p;
        return 0;
 
    while (b > 0)
    {
         
        // If a is odd,
        // multiply x with result
        if (b % 2 == 1)
            res = (res * a) % mod;
 
        // b must be even now
        b = b >> 1; // b = b/2
        a = (a * a) % mod;
    }
    return res;
}
 
// DFS traversal of the nodes
static void dfs(int i, boolean []visited)
{
     
    // Mark the current
    // node as visited
    visited[i] = true;
     
    // Increment  the size of the
    // current component
    size++;
 
    // Recur for all the vertices
    // adjacent to this node
    for(int nbr : G[i])
    {
        if (!visited[nbr])
        {
            dfs(nbr, visited);
        }
    }
}
 
// Function to calculate the
// final answer
static void totalSequences(int n, int k)
{
     
    // Mark all the vertices as
    // not visited initially
    boolean []visited = new boolean[n + 1];
 
    // Subtract (size^k) from the answer
    // for different components
    for(int i = 1; i <= n; i++)
    {
        if (!visited[i])
        {
            size = 0;
            dfs(i, visited);
            ans -= power(size, k);
            ans += mod;
            ans = ans % mod;
        }
    }
}
 
// Function to add edges to the graph
static void addEdge(int x, int y, int color)
{
     
    // If the colour is green,
    // include it in the graph
    if (color == 0)
    {
        G[x].add(y);
        G[y].add(x);
    }
}
 
// Driver code
public static void main(String[] args)
{
    for(int i = 0; i < G.length; i++)
        G[i] = new Vector();
         
    // Number of node in the tree
    int n = 3;
 
    // Size of sequence
    int k = 3;
 
    // Initialize the result as n^k
    ans = power(n, k);
     
    /* 2
     /   \
    1     3
    Let us create binary tree as shown
    in above example */
    addEdge(1, 2, 1);
    addEdge(2, 3, 1);
 
    totalSequences(n, k);
    System.out.print(ans + "\n");
}
}
 
// This code is contributed by Amit Katiyar


Python3
# Python3 program for the above approach
mod = 1e9 + 7
N = 1e5 + 1
 
# List to store the graph
G = [0] * int(N)
 
# Iterative Function to calculate
# (ab) % mod in O(log b)
def power(a, b):
 
    # Initialize result
    res = 1
 
    # Update x if it is more than
    # or equal to p
    a = a % mod
 
    if a == 0:
         
        # In case x is divisible by p;
        return 0
 
    while b > 0:
 
        # If a is odd,
        # multiply x with result
        if b & 1:
            res = (res * a) % mod
 
        # b must be even now
        b = b >> 1 # b = b/2
        a = (a * a) % mod
 
    return res
 
# DFS traversal of the nodes
def dfs(i, size, visited):
 
    # Mark the current
    # node as visited
    visited[i] = True
 
    # Increment the size of the
    # current component
    size[0] += 1
 
    # Recur for all the vertices
    # adjacent to this node
    for nbr in range(G[i]):
        if not visited[nbr]:
            dfs(nbr, size, visited)
 
# Function to calculate the
# final answer
def totalSequences(ans, n, k):
 
    # Mark all the vertices as
    # not visited initially
    visited = [False] * (n + 1)
 
    # Subtract (size^k) from the answer
    # for different components
    for i in range(1, n + 1):
        if not visited[i]:
            size = [0]
            dfs(i, size, visited)
             
            ans[0] -= power(size[0], k)
            ans[0] += mod
            ans[0] = ans[0] % mod
 
# Function to add edges to the graph
def addEdge(x, y, color):
 
    # If the colour is green,
    # include it in the graph
    if color == 0:
        G[x].append(y)
        G[y].append(x)
 
# Driver code
if __name__ == '__main__':
 
    # Number of node in the tree
    n = 3
 
    # Size of sequence
    k = 3
 
    # Initialize the result as n^k
    ans = [power(n, k)]
 
    """
      2
     / \
    1   3
         
    Let us create binary tree as shown
    in above example
    """
    addEdge(1, 2, 1)
    addEdge(2, 3, 1)
 
    totalSequences(ans, n, k)
    print(int(ans[0]))
 
# This code is contributed by Shivam Singh


C#
// C# implementation of the
// above approach
using System;
using System.Collections.Generic;
class GFG{
 
static int mod = (int)(1e9 + 7);
static int N = (int)(1e5 + 1);
static  int size;
static int ans;
 
// List to store the graph
static List []G =
       new List[N];
 
// Iterative Function to
// calculate (ab)
// % mod in O(log b)
static int power(int a,
                 int b)
{
  // Initialize result
  int res = 1;
 
  // Update x if it is
  // more than or equal
  // to p
  a = a % mod;
 
  if (a == 0)
 
    // In case x is
    // divisible by p;
    return 0;
 
  while (b > 0)
  {
    // If a is odd,
    // multiply x
    // with result
    if (b % 2 == 1)
      res = (res * a) % mod;
 
    // b must be even now
    // b = b/2
    b = b >> 1;
     
    a = (a * a) % mod;
  }
  return res;
}
 
// DFS traversal of the nodes
static void dfs(int i,
                bool []visited)
{
  // Mark the current
  // node as visited
  visited[i] = true;
 
  // Increment  the size of the
  // current component
  size++;
 
  // Recur for all the vertices
  // adjacent to this node
  foreach(int nbr in G[i])
  {
    if (!visited[nbr])
    {
      dfs(nbr, visited);
    }
  }
}
 
// Function to calculate the
// readonly answer
static void totalSequences(int n,
                           int k)
{
  // Mark all the vertices as
  // not visited initially
  bool []visited = new bool[n + 1];
 
  // Subtract (size^k) from the
  // answer for different components
  for(int i = 1; i <= n; i++)
  {
    if (!visited[i])
    {
      size = 0;
      dfs(i, visited);
      ans -= power(size, k);
      ans += mod;
      ans = ans % mod;
    }
  }
}
 
// Function to add edges
// to the graph
static void addEdge(int x,
                    int y,
                    int color)
{
  // If the colour is green,
  // include it in the graph
  if (color == 0)
  {
    G[x].Add(y);
    G[y].Add(x);
  }
}
 
// Driver code
public static void Main(String[] args)
{
  for(int i = 0; i < G.Length; i++)
    G[i] = new List();
 
  // Number of node
  // in the tree
  int n = 3;
 
  // Size of sequence
  int k = 3;
 
  // Initialize the
  // result as n^k
  ans = power(n, k);
 
  /*   2
     /   \
    1     3
    Let us create binary tree
    as shown in above example */
  addEdge(1, 2, 1);
  addEdge(2, 3, 1);
 
  totalSequences(n, k);
  Console.Write(ans + "\n");
}
}
 
// This code is contributed by Rajput-Ji


Javascript


输出:
24

时间复杂度: O(N),因为 DFS 遍历需要 O(Vertices + Edges) == O(N + (N-1)) == O(N) ) 复杂度。