java-20-图的算法-扩展

177 阅读2分钟

1、二分图判定

场景:使用二分图存储每一个演员和参演电影的关系
判断是否是一个二分图,类似于用两种颜色将所有的节点染色,并且两头的颜色不同。如果可以则是一个二分图,如果不可以则不是

0.png

**//二叉树的遍历框架
void traverse(TreeNode root){
    if(root = =null) return;
    //前序遍历框架
    traverse(root.left);
    traverse(root.right);
    //后序遍历框架
}**

//多叉树遍历框架
void traverse(TreeNode root){
    if(root==null) return;
    for(Treenode next :root.children){
        traverse(next);
    }
}
//图的遍历框架 DFS
boolean visted[];  //注意:还需要对数组进行初始化
void traverse(Graph graph,int s){
    //先判断是否访问过
    if(visted[s]) return;
    //前序位置:是在节点将要进入的时候
    visted[s]=true;
    for(int t:graph[s]){
       traverse(graph,t);
    }
}

//对于二分图的判定,需要修改if的判定
//图的遍历框架 DFS
boolean visted[];  //注意:还需要对数组进行初始化
void traverse(Graph graph,int s){
    //前序位置:是在节点将要进入的时候
    visted[s]=true;
    for(int t:graph[s]){
       if(!visited[t]){
          traverse(graph,t);
       }
    }
}

二分图的判定方法

traverse 函数一边遍历节点,一边给节点染色,尝试让每对相邻节点的颜色都不一样
没访问过,则涂上相同的颜色,访问过则判断颜色而是否相同

/* 图遍历框架 */ 
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 的颜色 
                    // 若相同,则此图不是二分图 
                    }
               }
       }

二分图的判定函数

    //输入的是邻接表
    boolean ErFenTu;
    boolean[] visted;
    boolean[] color;
    boolean isBinary(int[][] graph){
        //获取的是节点的数目 获取线的条数 则是graph[0].length
        int n = graph.length;  //注意:数组的长度是.length 字符串的长度是lenngth()
        visted=new boolean[n];
        //循环遍历其中的每一个结点
        for(int i = 0;i < n;i++){
            if(!visted[i]){
                traverse(i,graph);
            }
        }
    }
    //如果相邻的遍历过了,比较颜色,如果没有,给他相反的颜色
    //遍历
    void traverse(int s, int[][] graph){
         visted[s]=true;
         for(int t:graph[s]){
             if(!visted[s]){
               //给他染色
               color[t]=!color[s];
               travserse(t,graph);
             }else{
                 if(color[t]==color[s]){
                    //如果颜色相等,则不是
                    return !ErFenTu;
                 }
             }
         }
         return ErFenTu;
    }

二、并查集算法

class UF {
    /* 将 p 和 q 连接 */ 
    public void union(int p, int q);
    /* 判断 p 和 q 是否连通 */ 
    public boolean connected(int p, int q);
    /* 返回图中有多少个连通分量 */
    public int count();
 }
 
 
 class UF {
    // 记录连通分量
    private int count;
    // 节点 x 的节点是 parent[x]
    private int[] parent;

    /* 构造函数,n 为图的节点总数 */
    public UF(int n) {
        // 一开始互不连通
        this.count = n;
        // 父节点指针初始指向自己
        parent = new int[n];
        for (int i = 0; i < n; i++)
            parent[i] = i;
    }

    /* 其他函数 */
}