📜  通过分配方向使给定的段不重叠

📅  最后修改于: 2021-10-25 04:49:00             🧑  作者: Mango

给定一个数组arr[][]N{L, R, V}形式的段组成,其中[L, R]表示在任何方向上速度为V的段,任务是检查是否可以分配所有线段的左或右方向,以便它们在很长一段时间后不会相交。

例子:

方法:根据以下观察可以解决给定的问题:

  • 情况一:当两段速度不同时:
    • 这个想法是为两个段分配相同的方向。
    • 因此,经过很长一段时间后,这些段将永远不会相交或重叠。有可能在这段时间之间,段的某处重叠。然后,最终一个细分市场将超过另一个细分市场。
  • 情况 2 :当两个线段的速度相同,但在 t = 0 处不相交时:
    • 这个想法是为它们分配相同的运动方向到两个部分。
    • 由于它们的相对位置不会因相同的速度和相同的方向而改变,因此在无限时间之后,它们的相对位置将保持不变,不会重叠。
  • 情况3 :当两个段的速度相同时,它们最初重叠/相交。
    • 这个想法是为它们分配相反的运动方向。

以下示例说明了上述所有情况:

根据上述观察,想法是为所有重叠段创建一个图,并检查创建的图是否是二部图。如果创建的图是二部图,则可以为所有线段分配方向,使它们在很长一段时间后不相交。因此,打印“是” 。否则,打印“否”
请按照以下步骤解决问题:

  • 从给定的数组arr[][]生成所有可能的不同元素对。如果任何一对段(arr[i], arr[j])重叠,则在它们之间添加无向边(i, j)
  • 检查给定图对于[0, N – 1]范围内的所有可能节点是否是二部图。如果发现是真的,则打印“是” 。否则,打印“否”

下面是上述方法的实现:

C++
// C++ program for the above approach
 
#include 
using namespace std;
 
// Stores the details of the Segment
struct Node {
    int L, R, V;
};
 
// Function to check whether the
// graph is bipartite or not
bool check(vector Adj[], int Src,
           int N, bool visited[])
{
    int color[N] = { 0 };
 
    // Mark source node as visited
    visited[Src] = true;
 
    queue q;
 
    // Push the source vertex in queue
    q.push(Src);
 
    while (!q.empty()) {
 
        // Get the front of the queue
        int u = q.front();
        q.pop();
 
        // Assign the color
        // to the popped node
        int Col = color[u];
 
        // Traverse the adjacency
        // list of the node u
        for (int x : Adj[u]) {
 
            // If any node is visited &
            // a different colors has been
            // assigned, then return false
            if (visited[x] == true
                && color[x] == Col) {
                return false;
            }
 
            else if (visited[x] == false) {
 
                // Set visited[x]
                visited[x] = true;
 
                // Push the node x
                // into the queue
                q.push(x);
 
                // Update color of node
                color[x] = 1 - Col;
            }
        }
    }
 
    // If the graph is bipartite
    return true;
}
 
// Function to add an edge
// between the nodes u and v
void addEdge(vector Adj[],
             int u, int v)
{
    Adj[u].push_back(v);
    Adj[v].push_back(u);
}
 
// Function to check if the assignment
// of direction can be possible to all
// the segments, such that they do not
// intersect after a long period of time
void isPossible(struct Node Arr[], int N)
{
    // Stores the adjacency list
    // of the created graph
    vector Adj[N];
 
    // Generate all possible pairs
    for (int i = 0; i < N - 1; i++) {
 
        for (int j = i + 1; j < N; j++) {
 
            // If segments do not overlap
            if (Arr[i].R < Arr[j].L
                || Arr[i].L > Arr[j].R) {
                continue;
            }
 
            // Otherwise, the segments overlap
            else {
 
                if (Arr[i].V == Arr[j].V) {
 
                    // If both segments have
                    // same speed, then add an edge
                    addEdge(Adj, i, j);
                }
            }
        }
    }
 
    // Keep the track of visited nodes
    bool visited[N] = { false };
 
    // Iterate for all possible nodes
    for (int i = 0; i < N; i++) {
 
        if (visited[i] == false
            && Adj[i].size() > 0) {
 
            // Check whether graph is
            // bipartite or not
            if (check(Adj, i, N, visited)
                == false) {
 
                cout << "No";
                return;
            }
        }
    }
 
    // If the graph is bipartite
    cout << "Yes";
}
 
// Driver Code
int main()
{
    struct Node arr[] = {
        { 5, 7, 2 }, { 4, 6, 1 },
        { 1, 5, 2 }, { 6, 5, 1 }
    };
    int N = sizeof(arr) / sizeof(arr[0]);
 
    isPossible(arr, N);
 
    return 0;
}


Java
// Java program for the above approach
import java.io.*;
import java.lang.*;
import java.util.*;
 
class GFG{
 
// Stores the details of the Segment
static class Node
{
    int L, R, V;
 
    Node(int L, int R, int V)
    {
        this.L = L;
        this.R = R;
        this.V = V;
    }
}
 
// Function to check whether the
// graph is bipartite or not
static boolean check(ArrayList Adj[], int Src,
                     int N, boolean visited[])
{
    int color[] = new int[N];
 
    // Mark source node as visited
    visited[Src] = true;
 
    ArrayDeque q = new ArrayDeque<>();
 
    // Push the source vertex in queue
    q.addLast(Src);
 
    while (!q.isEmpty())
    {
         
        // Get the front of the queue
        int u = q.removeFirst();
 
        // Assign the color
        // to the popped node
        int Col = color[u];
 
        // Traverse the adjacency
        // list of the node u
        for(int x : Adj[u])
        {
             
            // If any node is visited &
            // a different colors has been
            // assigned, then return false
            if (visited[x] == true && color[x] == Col)
            {
                return false;
            }
 
            else if (visited[x] == false)
            {
                 
                // Set visited[x]
                visited[x] = true;
 
                // Push the node x
                // into the queue
                q.addLast(x);
 
                // Update color of node
                color[x] = 1 - Col;
            }
        }
    }
 
    // If the graph is bipartite
    return true;
}
 
// Function to add an edge
// between the nodes u and v
static void addEdge(ArrayList Adj[], int u,
                                              int v)
{
    Adj[u].add(v);
    Adj[v].add(u);
}
 
// Function to check if the assignment
// of direction can be possible to all
// the segments, such that they do not
// intersect after a long period of time
static void isPossible(Node Arr[], int N)
{
     
    // Stores the adjacency list
    // of the created graph
    @SuppressWarnings("unchecked")
    ArrayList [] Adj = (ArrayList[])new ArrayList[N];
 
    // Initialize
    for(int i = 0; i < N; i++)
        Adj[i] = new ArrayList<>();
 
    // Generate all possible pairs
    for(int i = 0; i < N - 1; i++)
    {
        for(int j = i + 1; j < N; j++)
        {
             
            // If segments do not overlap
            if (Arr[i].R < Arr[j].L ||
                Arr[i].L > Arr[j].R)
            {
                continue;
            }
 
            // Otherwise, the segments overlap
            else
            {
                if (Arr[i].V == Arr[j].V)
                {
                     
                    // If both segments have
                    // same speed, then add an edge
                    addEdge(Adj, i, j);
                }
            }
        }
    }
 
    // Keep the track of visited nodes
    boolean visited[] = new boolean[N];
 
    // Iterate for all possible nodes
    for(int i = 0; i < N; i++)
    {
        if (visited[i] == false && Adj[i].size() > 0)
        {
             
            // Check whether graph is
            // bipartite or not
            if (check(Adj, i, N, visited) == false)
            {
                 
                System.out.println("No");
                return;
            }
        }
    }
 
    // If the graph is bipartite
    System.out.println("Yes");
}
 
// Driver Code
public static void main(String[] args)
{
    Node arr[] = { new Node(5, 7, 2), new Node(4, 6, 1),
                   new Node(1, 5, 2), new Node(6, 5, 1) };
 
    int N = arr.length;
 
    isPossible(arr, N);
}
}
 
// This code is contributed by Kingash


Python3
# Python3 program for the above approach
from collections import deque
 
# Function to check whether the
# graph is bipartite or not
def check(Adj, Src, N, visited):
     
    color = [0] * N
 
    # Mark source node as visited
    visited = [True] * Src
    q = deque()
 
    # Push the source vertex in queue
    q.append(Src)
 
    while (len(q) > 0):
         
        # Get the front of the queue
        u = q.popleft()
        # q.pop()
 
        # Assign the color
        # to the popped node
        Col = color[u]
 
        # Traverse the adjacency
        # list of the node u
        for x in Adj[u]:
             
            # If any node is visited &
            # a different colors has been
            # assigned, then return false
            if (visited[x] == True and
                color[x] == Col):
                return False
                 
            elif (visited[x] == False):
 
                # Set visited[x]
                visited[x] = True
 
                # Push the node x
                # into the queue
                q.append(x)
 
                # Update color of node
                color[x] = 1 - Col
 
    # If the graph is bipartite
    return True
 
# Function to add an edge
# between the nodes u and v
def addEdge(Adj, u, v):
     
    Adj[u].append(v)
    Adj[v].append(u)
    return Adj
 
# Function to check if the assignment
# of direction can be possible to all
# the segments, such that they do not
# intersect after a long period of time
def isPossible(Arr, N):
     
    # Stores the adjacency list
    # of the created graph
    Adj = [[] for i in range(N)]
 
    # Generate all possible pairs
    for i in range(N - 1):
        for j in range(i + 1, N):
             
            # If segments do not overlap
            if (Arr[i][0] < Arr[j][1] or
                Arr[i][1] > Arr[j][0]):
                continue
 
            # Otherwise, the segments overlap
            else:
 
                if (Arr[i][2] == Arr[j][2]):
 
                    # If both segments have
                    # same speed, then add an edge
                    Adj = addEdge(Adj, i, j)
 
    # Keep the track of visited nodes
    visited = [False] * N
     
    # Iterate for all possible nodes
    for i in range(N):
        if (visited[i] == False and len(Adj[i]) > 0):
 
            # Check whether graph is
            # bipartite or not
            if (check(Adj, i, N, visited) == False):
                print ("No")
                return
 
    # If the graph is bipartite
    print ("Yes")
 
# Driver Code
if __name__ == '__main__':
     
    arr = [ [ 5, 7, 2 ], [ 4, 6, 1 ],
            [ 1, 5, 2 ], [ 6, 5, 1 ] ]
    N = len(arr)
 
    isPossible(arr, N)
 
# This code is contributed by mohit kumar 29


C#
// C# program for the above approach
using System;
using System.Collections.Generic;
 
class GFG{
 
// Stores the details of the Segment
class Node
{
    public int L, R, V;
};
 
static Node newNode(int L, int R, int V)
{
    Node temp = new Node();
    temp.L = L;
    temp.R = R;
    temp.V = V;
    return temp;
}
 
// Function to check whether the
// graph is bipartite or not
static bool check(List []Adj, int Src,
                     int N, bool []visited)
{
    int []color = new int[N];
 
    // Mark source node as visited
    visited[Src] = true;
 
    Queue q = new Queue();
 
    // Push the source vertex in queue
    q.Enqueue(Src);
 
    while (q.Count > 0)
    {
         
        // Get the front of the queue
        int u = q.Peek();
        q.Dequeue();
 
        // Assign the color
        // to the popped node
        int Col = color[u];
 
        // Traverse the adjacency
        // list of the node u
        foreach (int x in Adj[u])
        {
             
            // If any node is visited &
            // a different colors has been
            // assigned, then return false
            if (visited[x] == true &&
                  color[x] == Col)
            {
                return false;
            }
 
            else if (visited[x] == false)
            {
                 
                // Set visited[x]
                visited[x] = true;
 
                // Push the node x
                // into the queue
                q.Enqueue(x);
 
                // Update color of node
                color[x] = 1 - Col;
            }
        }
    }
 
    // If the graph is bipartite
    return true;
}
 
// Function to add an edge
// between the nodes u and v
static void addEdge(List []Adj, int u, int v)
{
    Adj[u].Add(v);
    Adj[v].Add(u);
}
 
// Function to check if the assignment
// of direction can be possible to all
// the segments, such that they do not
// intersect after a long period of time
static void isPossible(Node []Arr, int N)
{
     
    // Stores the adjacency list
    // of the created graph
    List [] Adj = new List[N];
 
    // Initialize
    for(int i = 0; i < N; i++)
        Adj[i] = new List();
 
    // Generate all possible pairs
    for(int i = 0; i < N - 1; i++)
    {
        for(int j = i + 1; j < N; j++)
        {
             
            // If segments do not overlap
            if (Arr[i].R < Arr[j].L ||
                Arr[i].L > Arr[j].R)
            {
                continue;
            }
 
            // Otherwise, the segments overlap
            else
            {
                if (Arr[i].V == Arr[j].V)
                {
                     
                    // If both segments have
                    // same speed, then add an edge
                    addEdge(Adj, i, j);
                }
            }
        }
    }
 
    // Keep the track of visited nodes
    bool []visited = new bool[N];
 
    // Iterate for all possible nodes
    for(int i = 0; i < N; i++)
    {
        if (visited[i] == false && Adj[i].Count > 0)
        {
             
            // Check whether graph is
            // bipartite or not
            if (check(Adj, i, N, visited) == false)
            {
                Console.Write("No");
                return;
            }
        }
    }
 
    // If the graph is bipartite
    Console.Write("Yes");
}
 
// Driver Code
public static void Main()
{
    Node []arr = { newNode(5, 7, 2), newNode(4, 6, 1),
                   newNode(1, 5, 2), newNode(6, 5, 1) };
 
    int N = arr.Length;
     
    isPossible(arr, N);
}
}
 
// This code is contributed by SURENDRA_GANGWAR


Javascript


输出:
Yes

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

如果您希望与专家一起参加现场课程,请参阅DSA 现场工作专业课程学生竞争性编程现场课程