📜  频道分配问题

📅  最后修改于: 2022-05-13 01:57:54.441000             🧑  作者: Mango

频道分配问题

有 M 个发射站和 N 个接收站。给定一个矩阵,该矩阵跟踪要从给定发送器发送到接收器的数据包数量。如果矩阵的第 (i;j) 项是 k,则表示此时站 i 有 k 个数据包要传输到站 j。
在一个时隙内,发送器只能发送一个数据包,而接收器只能接收一个数据包。找到信道分配,以便在下一个时隙中从发送器传输到接收器的数据包数量最多。
例子:

0 2 0
3 0 1
2 4 0

以上是输入格式。我们称上面的矩阵为 M。每个值 M[i; j] 表示发送器“i”必须发送到接收器“j”的数据包数。输出应该是:

The number of maximum packets sent in the time slot is 3
T1 -> R2
T2 -> R3
T3 -> R1 

请注意,在任何时隙中可以传输的最大数据包数为 min(M, N)。
算法:
发送方和接收方之间的通道分配问题可以很容易地转化为最大二分匹配(MBP)问题,可以通过将其转化为流网络来解决。
第 1 步:构建流网络
流网络中必须有源和汇。因此,我们添加了一个虚拟源并将源的边添加到所有发送者。同样,将所有接收器的边添加到虚拟接收器。所有添加边的容量标记为 1 个单位。
第 2 步:找到最大流量。
我们使用Ford-Fulkerson算法在步骤1中建立的流网络中找到最大流量。最大流量实际上是在一个时隙内不存在带宽干扰的情况下可以传输的最大数据包数。
执行:
让我们首先定义输入和输出形式。输入采用 Edmonds 矩阵的形式,它是一个 2D 数组 'table[M][N]',有 M 行(对于 M 个发送者)和 N 列(对于 N 个接收者)。值 table[i][j] 是必须从发送器“i”发送到接收器“j”的数据包数。输出是在一个时隙内可以传输而不受带宽干扰的最大数据包数。
实现这一点的一种简单方法是创建一个矩阵,该矩阵表示具有 M+N+2 个顶点的有向图的邻接矩阵表示。调用矩阵的 fordFulkerson()。此实现需要 O((M+N)*(M+N)) 额外空间。
使用图是二分的这一事实可以减少额外的空间并简化代码。这个想法是使用 DFS 遍历来找到发送器的接收器(类似于 Ford-Fulkerson 中的增强路径)。我们为每个申请人调用 bpm(),bpm() 是基于 DFS 的函数,它尝试将接收者分配给发送者的所有可能性。在 bpm() 中,我们一个接一个地尝试发送者 'u' 感兴趣的所有接收者,直到我们找到一个接收者或所有接收者都被尝试但没有运气。
对于我们尝试的每个接收器,我们执行以下操作:
如果接收者没有分配给任何人,我们只需将其分配给发送者并返回 true。如果一个接收者被分配给其他人,比如 x,那么我们递归地检查 x 是否可以被分配给另一个接收者。为了确保 x 不会再次获得相同的接收者,我们在对 x 进行递归调用之前将接收者标记为“v”。如果 x 可以得到其他接收者,我们将发送者更改为接收者“v”并返回 true。我们使用一个数组 maxR[0..N-1] 来存储分配给不同接收者的发送者。
如果 bmp() 返回 true,则表示流网络中存在增广路径,并且在 maxBPM() 中将 1 个单位的流添加到结果中。
时间和空间复杂度分析:
在二分匹配问题的情况下,F ? |V|因为只能有 |V|来自源节点的可能边。所以总运行时间是 O(m'n) = O((m + n)n)。空间复杂度也从 O ((M+N)*(M+N)) 大幅降低到大小为 M 的一维数组,从而存储了 M 和 N 之间的映射。

C
#include 
#include 
#include 
#define M 3
#define N 4
using namespace std;
 
// A Depth First Search based recursive function that returns true
// if a matching for vertex u is possible
bool bpm(int table[M][N], int u, bool seen[], int matchR[])
{
    // Try every receiver one by one
    for (int v = 0; v < N; v++)
    {
        // If sender u has packets to send to receiver v and
        // receiver v is not already mapped to any other sender
        // just check if the number of packets is greater than '0'
        // because only one packet can be sent in a time frame anyways
        if (table[u][v]>0 && !seen[v])
        {
            seen[v] = true; // Mark v as visited
 
            // If receiver 'v' is not assigned to any sender OR
            // previously assigned sender for receiver v (which is
            // matchR[v]) has an alternate receiver available. Since
            // v is marked as visited in the above line, matchR[v] in
            // the following recursive call will not get receiver 'v' again
            if (matchR[v] < 0 || bpm(table, matchR[v], seen, matchR))
            {
                matchR[v] = u;
                return true;
            }
        }
    }
    return false;
}
 
// Returns maximum number of packets that can be sent parallelly in 1
// time slot from sender to receiver
int maxBPM(int table[M][N])
{
    // An array to keep track of the receivers assigned to the senders.
    // The value of matchR[i] is the sender ID assigned to receiver i.
    // the value -1 indicates nobody is assigned.
    int matchR[N];
 
    // Initially all receivers are not mapped to any senders
    memset(matchR, -1, sizeof(matchR));
 
    int result = 0; // Count of receivers assigned to senders
    for (int u = 0; u < M; u++)
    {
        // Mark all receivers as not seen for next sender
        bool seen[N];
        memset(seen, 0, sizeof(seen));
 
        // Find if the sender 'u' can be assigned to the receiver
        if (bpm(table, u, seen, matchR))
            result++;
    }
 
    cout << "The number of maximum packets sent in the time slot is "
         << result << "\n";
 
    for (int x=0; x R" << x+1 << "\n";
    return result;
}
 
// Driver program to test above function
int main()
{
    int table[M][N] = {{0, 2, 0}, {3, 0, 1}, {2, 4, 0}};
    int max_flow = maxBPM(table);
    return 0;
}


Java
import java.util.*;
class GFG
{
static int M = 3;
static int N = 3;
 
// A Depth First Search based recursive function
// that returns true if a matching for vertex u is possible
static boolean bpm(int table[][], int u,
                   boolean seen[], int matchR[])
{
    // Try every receiver one by one
    for (int v = 0; v < N; v++)
    {
        // If sender u has packets to send
        // to receiver v and receiver v is not
        // already mapped to any other sender
        // just check if the number of packets is
        // greater than '0' because only one packet
        // can be sent in a time frame anyways
        if (table[u][v] > 0 && !seen[v])
        {
            seen[v] = true; // Mark v as visited
 
            // If receiver 'v' is not assigned to
            // any sender OR previously assigned sender
            // for receiver v (which is matchR[v]) has an
            // alternate receiver available. Since v is
            // marked as visited in the above line,
            // matchR[v] in the following recursive call
            // will not get receiver 'v' again
            if (matchR[v] < 0 || bpm(table, matchR[v],
                                      seen, matchR))
            {
                matchR[v] = u;
                return true;
            }
        }
    }
    return false;
}
 
// Returns maximum number of packets
// that can be sent parallelly in
// 1 time slot from sender to receiver
static int maxBPM(int table[][])
{
    // An array to keep track of the receivers
    // assigned to the senders. The value of matchR[i]
    // is the sender ID assigned to receiver i.
    // The value -1 indicates nobody is assigned.
    int []matchR = new int[N];
 
    // Initially all receivers are
    // not mapped to any senders
    Arrays.fill(matchR, -1);
 
    int result = 0; // Count of receivers assigned to senders
    for (int u = 0; u < M; u++)
    {
        // Mark all receivers as not seen for next sender
        boolean []seen = new boolean[N];
        Arrays.fill(seen, false);
 
        // Find if the sender 'u' can be
        // assigned to the receiver
        if (bpm(table, u, seen, matchR))
            result++;
    }
 
    System.out.println("The number of maximum packets" +
                       " sent in the time slot is " + result);
 
    for (int x = 0; x < N; x++)
        if (matchR[x] + 1 != 0)
            System.out.println("T" + (matchR[x] + 1) +
                               "-> R" + (x + 1));
    return result;
}
 
// Driver Code
public static void main(String[] args)
{
    int table[][] = {{0, 2, 0},
                     {3, 0, 1},
                     {2, 4, 0}};
     
    maxBPM(table);
}
}
 
// This code is contributed by Rajput-Ji


Python3
# A Depth First Search based recursive
# function that returns true if a matching
# for vertex u is possible
def bpm(table, u, seen, matchR):
    global M, N
     
    # Try every receiver one by one
    for v in range(N):
         
        # If sender u has packets to send to
        # receiver v and receiver v is not
        # already mapped to any other sender
        # just check if the number of packets
        # is greater than '0' because only one
        # packet can be sent in a time frame anyways
        if (table[u][v] > 0 and not seen[v]):
            seen[v] = True # Mark v as visited
 
            # If receiver 'v' is not assigned to any
            # sender OR previously assigned sender
            # for receiver v (which is matchR[v]) has
            # an alternate receiver available. Since
            # v is marked as visited in the above line, 
            # matchR[v] in the following recursive call
            # will not get receiver 'v' again
            if (matchR[v] < 0 or bpm(table, matchR[v],
                                       seen, matchR)):
                matchR[v] = u
                return True
    return False
 
# Returns maximum number of packets
# that can be sent parallelly in 1
# time slot from sender to receiver
def maxBPM(table):
    global M, N
     
    # An array to keep track of the receivers
    # assigned to the senders. The value of
    # matchR[i] is the sender ID assigned to
    # receiver i. The value -1 indicates nobody
    # is assigned.
 
    # Initially all receivers are not mapped
    # to any senders
    matchR = [-1] * N
 
    result = 0 # Count of receivers assigned to senders
    for u in range(M):
         
        # Mark all receivers as not seen
        # for next sender
        seen = [0] * N
 
        # Find if the sender 'u' can be assigned
        # to the receiver
        if (bpm(table, u, seen, matchR)):
            result += 1
 
    print("The number of maximum packets sent",
          "in the time slot is", result)
 
    for x in range(N):
        if (matchR[x] + 1 != 0):
            print("T", matchR[x] + 1, "-> R", x + 1)
    return result
 
# Driver Code
M = 3
N = 4
 
table = [[0, 2, 0], [3, 0, 1], [2, 4, 0]]
max_flow = maxBPM(table)
 
# This code is contributed by PranchalK


C#
// C# implementation of the above approach
using System;
     
class GFG
{
static int M = 3;
static int N = 3;
 
// A Depth First Search based recursive function
// that returns true if a matching for vertex u is possible
static Boolean bpm(int [,]table, int u,
                   Boolean []seen, int []matchR)
{
    // Try every receiver one by one
    for (int v = 0; v < N; v++)
    {
        // If sender u has packets to send
        // to receiver v and receiver v is not
        // already mapped to any other sender
        // just check if the number of packets is
        // greater than '0' because only one packet
        // can be sent in a time frame anyways
        if (table[u, v] > 0 && !seen[v])
        {
            seen[v] = true; // Mark v as visited
 
            // If receiver 'v' is not assigned to
            // any sender OR previously assigned sender
            // for receiver v (which is matchR[v]) has an
            // alternate receiver available. Since v is
            // marked as visited in the above line,
            // matchR[v] in the following recursive call
            // will not get receiver 'v' again
            if (matchR[v] < 0 || bpm(table, matchR[v],
                                     seen, matchR))
            {
                matchR[v] = u;
                return true;
            }
        }
    }
    return false;
}
 
// Returns maximum number of packets
// that can be sent parallelly in
// 1 time slot from sender to receiver
static int maxBPM(int [,]table)
{
    // An array to keep track of the receivers
    // assigned to the senders. The value of matchR[i]
    // is the sender ID assigned to receiver i.
    // The value -1 indicates nobody is assigned.
    int []matchR = new int[N];
 
    // Initially all receivers are
    // not mapped to any senders
    for(int i = 0; i < N; i++)
        matchR[i] = -1;
 
    int result = 0; // Count of receivers assigned to senders
    for (int u = 0; u < M; u++)
    {
        // Mark all receivers as not seen for next sender
        Boolean []seen = new Boolean[N];
 
        // Find if the sender 'u' can be
        // assigned to the receiver
        if (bpm(table, u, seen, matchR))
            result++;
    }
 
    Console.WriteLine("The number of maximum packets" +
                      " sent in the time slot is " + result);
 
    for (int x = 0; x < N; x++)
        if (matchR[x] + 1 != 0)
            Console.WriteLine("T" + (matchR[x] + 1) +
                              "-> R" + (x + 1));
    return result;
}
 
// Driver Code
public static void Main(String[] args)
{
    int [,]table = {{0, 2, 0},
                    {3, 0, 1},
                    {2, 4, 0}};
     
    maxBPM(table);
}
}
 
// This code is contributed by 29AjayKumar


Javascript


输出:

The number of maximum packets sent in the time slot is 3
T3-> R1
T1-> R2
T2-> R3