"Question Diary 10"-Bipart Picture

The concept of bipartite graph

The vertex set of a bipartite graph can be divided into two disjoint subsets. The two vertices attached to each edge in the graph belong to these two subsets, and the vertices in the two subsets are not adjacent.

Just looking at the definition may make us feel obscure. Simply put, a bipartite graph meets the following characteristics: the two points connected by each edge in the graph do not belong to the same set (if we paint each point in the graph One color, two colors in the picture: then the colors of the two points on each side must be different)

 

First of all, bipartite graphs, as a special graph model, are used by many advanced graph algorithms (such as maximum flow algorithms). However, it is not particularly necessary for us to master these advanced algorithms. Interested readers can search for them by themselves.

From a simple and practical perspective, the bipartite graph structure can store data more efficiently in certain scenarios.

For example, we need a data structure to store the relationship between movies and actors: a certain movie must be starred by multiple actors, and a certain actor may appear in multiple movies. What data structure do you use to store this relationship?

Since it is a storage mapping relationship, the simplest thing is to use a hash table. We can use one to  HashMap<String, List<String>> store the mapping from movies to actor lists. If we give the name of a movie, we can quickly get the actors who starred in the movie.

But what if we give an actor's name and want to quickly get all the movies in which the actor has appeared? This requires "reverse indexing", perform some operations on the previous hash table, and create another hash table with actors as keys and movie lists as values.

Obviously, if a hash table is used for storage, two hash tables are needed to store the mapping of "each actor to the movie list" and the mapping of "each movie to the actor list". But if you use a "graph" structure to store it and connect the movie with the actors participating in it, it will naturally become a bipartite graph:

 

Bipartite diagram problem template

The solution template for the bipartite graph problem is as follows:

/* 图遍历框架 */
void traverse(Graph graph, boolean[] visited, int v) {
    visited[v] = true;
    // 遍历节点 v 的所有相邻节点 neighbor
    for (int neighbor : graph.neighbors(v)) {
        if (!visited[neighbor]) {
            // 相邻节点 neighbor 没有被访问过
            // 那么应该给节点 neighbor 涂上和节点 v 不同的颜色
            traverse(graph, visited, neighbor);
        } else {
            // 相邻节点 neighbor 已经被访问过
            // 那么应该比较节点 neighbor 和节点 v 的颜色
            // 若相同,则此图不是二分图
        }
    }
}

topic

Question description

Leetcode icon-default.png?t=N6B9https://leetcode.cn/problems/vEAB3K/

There is an undirected graph with n nodes in the graph. Each node has a unique number between 0 and n - 1.

Given a two-dimensional array graph, representing the graph, where graph[u] is a node array consisting of the adjacent nodes of node u. Formally, for every v in graph[u], there exists an undirected edge between node u and node v. This undirected graph also has the following properties:

There is no self-loop (graph[u] does not contain u).
There are no parallel edges (graph[u] contains no duplicate values).
If v is in graph[u], then u should also be in graph[v] (the graph is an undirected graph). This graph
may not be a connected graph, that is to say, there may not be a connection between the two nodes u and v. each other's paths.
Bipartite graph definition: If the node set of a graph can be divided into two independent subsets A and B, and one of the two nodes of each edge in the graph comes from the set A and one comes from the set B, then the graph will be is called a bipartite graph.

Returns true if the graph is a bipartite graph; otherwise, returns false.

Example 1:

Input: graph = [[1,2,3],[0,2],[0,1,3],[0,2]]
Output: false
Explanation: The node cannot be split into two independent subsets, So that each edge connects a node in one subset to a node in another subset.
Example 2:

Input: graph = [[1,3],[0,2],[1,3],[0,2]]
Output: true
Explanation: The nodes can be divided into two groups: {0, 2} and {1, 3}.

 

hint:

graph.length == n
1 <= n <= 100
0 <= graph[u].length < n
0 <= graph[u][i] <= n - 1
graph[u] will not contain u
graph[u All values ​​of ] are distinct from each other.
If graph[u] contains v, then graph[v] will also contain u.

Problem-solving ideas

In fact, this question is to make some changes based on traversing the graph structure: only traversal is required during graph traversal, but this question requires grouping the corresponding nodes (painting the nodes with corresponding colors) while traversing, so that We can ensure that each traversed node is painted with the corresponding color, and continue to recurse until we traverse the previously traversed nodes and find that the color of the current node is the same as the color of the node it is connected to. , a conflict occurs. At this time, we determine that this graph is not a bipartite graph (if it has not been traversed, it will be traversed and marked with color, and the next step of recursion will be carried out. If the node has been traversed before, it is necessary to compare the node with its Check whether the colors of the connected nodes conflict. If there is no conflict, just backtrace. If there is a conflict, use the identifier key we set before, set the key to false, and return directly)

Example code

class Solution {  
    //定义结果
    boolean ok=true;
    //定义数组判断保存颜色
    boolean[]color;
    //定义数组判断是否添加过
    boolean[]visited;
    public boolean isBipartite(int[][] graph) {
        int size=graph.length;
        //初始化
        color=new boolean[size];
        visited=new boolean[size];
        //避免存在多个图
        for(int i=0;i<size;++i){
            if(!visited[i])
            reverse(graph,i);
        }
        return ok;
    }
    //递归函数
    public void reverse(int[][]graph,int index){
        //出口条件
        if(!ok){
            return;
        }
        //将结果设置为参观
        visited[index]=true;
        //处理邻接节点
        for(int element:graph[index]){
            if(!visited[element]){
                color[element]=!color[index];
                //递归
                reverse(graph,element);
            }else{
                if(color[element]==color[index]){
                    ok=false;
                    return;
                }
            }
        }
    }
}

Guess you like

Origin blog.csdn.net/m0_65431718/article/details/131869839