1. 程式人生 > >並查集求最近公共祖先

並查集求最近公共祖先

package algorithm;

import java.io.BufferedOutputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.HashMap;

class UnionFind{

    int MAX = 17;
    int father[] = new int[MAX];
    int rank[] = new
int[MAX]; int indegree[] = new int[MAX]; int visited[] = new int[MAX]; HashMap<Integer, ArrayList<Integer>> tree,query; int ancestor[] = new int[MAX]; PrintWriter writer; void init(int n){ for(int i = 1; i <= n; i++){ father[i] = i; rank[i] = 1
; indegree[i] = 0; visited[i] = 0; ancestor[i] = 0; } try { writer = new PrintWriter(new BufferedOutputStream(new FileOutputStream("C:\\a.txt")),true); } catch (FileNotFoundException e) { e.printStackTrace(); } } int
Find_Set1(int x){ if(x != father[x]) father[x] = Find_Set(father[x]); return father[x]; } int Find_Set(int x){ if(x == father[x]) return x; else father[x] = Find_Set(father[x]); return father[x]; } int Union(int x, int y){ int a = Find_Set(x); int b = Find_Set(y); if(a == b) return 0; if(rank[a] >= rank[b]){ father[b] = a; writer.println("father["+b+"]="+a); rank[a] += rank[b]; }else{ father[a] = b; writer.println("father["+a+"]="+b); rank[b] += rank[a]; } return 1; } void LCA1(int u){ ancestor[u] = u; if(tree.get(u) != null) for(int unode : tree.get(u)){ LCA(unode); Union(u, unode); ancestor[Find_Set(u)] = u; } visited[u] = 1; if(query.get(u) != null) for(int vnode : query.get(u)){ if(visited[vnode] == 1) System.out.println(u + "和" + vnode +"的最近公共祖先為 :" + ancestor[Find_Set(vnode)]); } } void LCA(int u){ //System.out.println("u進入 u= "+u); writer.println("u進入 u= "+u); ancestor[u] = u; //System.out.println("ancestor["+u+"]="+u); writer.println("ancestor["+u+"]="+u); if(tree.get(u) != null){ ArrayList<Integer> ulist = tree.get(u); for(int unode : ulist){ LCA(unode); // System.out.println("return "); // System.out.println("合併 "+u +"和"+unode); writer.println("return " ); writer.println("合併 "+u +"和"+unode); Union(u, unode); ancestor[Find_Set(u)] = u; // System.out.println("Find_Set("+u+")="+Find_Set(u)); // System.out.println("ancestor["+u+"]="+Find_Set(u)); writer.println("Find_Set("+u+")="+Find_Set(u)); writer.println("ancestor["+Find_Set(u)+"]="+u); } } visited[u] = 1; // System.out.println(u+" 訪問標誌置1"); writer.println(u+" 訪問標誌置1"); if(query.get(u) != null){ writer.println("query "+u+" 不為空"); ArrayList<Integer> vlist = query.get(u); for(int vnode : vlist){ if(visited[vnode] == 1){ System.out.println(u + " 和 " + vnode +" 的最近公共祖先為 :" + ancestor[Find_Set(vnode)]); writer.println(u + " 和 " + vnode +" 的最近公共祖先為 :" + ancestor[Find_Set(vnode)]);} } } } void commonAncestor(int x, int y){ int n = 16; init(n); tree = new HashMap<Integer, ArrayList<Integer>>(); query = new HashMap<Integer, ArrayList<Integer>>(); ArrayList<Integer> list1 = new ArrayList<Integer>(); list1.add(5); indegree[5]++; list1.add(4);indegree[4]++; list1.add(1);indegree[1]++; tree.put(8, list1); ArrayList<Integer> list2 = new ArrayList<Integer>(); list2.add(9);indegree[9]++; tree.put(5, list2); ArrayList<Integer> list3 = new ArrayList<Integer>(); list3.add(6);indegree[6]++; list3.add(10);indegree[10]++; tree.put(4, list3); ArrayList<Integer> list4 = new ArrayList<Integer>(); list4.add(14);indegree[14]++; list4.add(13);indegree[13]++; tree.put(1, list4); ArrayList<Integer> list5 = new ArrayList<Integer>(); list5.add(15);indegree[15]++; list5.add(7);indegree[7]++; tree.put(6, list5); ArrayList<Integer> list6 = new ArrayList<Integer>(); list6.add(11);indegree[11]++; list6.add(16);indegree[16]++; list6.add(2);indegree[2]++; tree.put(10, list6); ArrayList<Integer> list7 = new ArrayList<Integer>(); list7.add(3);indegree[3]++; list7.add(12);indegree[12]++; tree.put(16, list7); ArrayList<Integer> q = new ArrayList<Integer>(); q.add(x); ArrayList<Integer> q2 = new ArrayList<Integer>(); q2.add(y); query.put(x, q2); query.put(y, q); LCA(8); /*System.out.println(uf.tree); System.out.println(uf.query); System.out.println(uf.indegree); for(int i = 0; i < indegree.length; i++) System.out.print(indegree[i] + " "); */ /*for(int i = 1; i <= n; i++){ if(indegree[i] == 0){ uf.LCA(i); break; } }*/ } } //並查集 + DFS 求最近公共祖先 public class UnionFind1 { public static void main(String[] a){ UnionFind uf = new UnionFind(); uf.commonAncestor(9, 7); } }

相關推薦

最近公共祖先

package algorithm; import java.io.BufferedOutputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; imp

tarjan算法最近公共祖先

技巧 splay 路徑壓縮 tor 沒有 blog 分析 father mar tarjian算法 LCA: LCA(Least Common Ancestor),顧名思義,是指在一棵樹中,距離兩個點最近的兩者的公共節點。也就是說,在兩個點通往根的道路上,肯定會有公共的節

Codeforces 278C Learning Languages() 連通塊

pre union get code fin const turn find ons Codeforces 278C Learning Languages(並查集) 求連通塊 為什麽最後還要getfather 一遍 比如 x 是 y 的父親 然後你 Union(x,

HDU 3018 Ant Trip (連通塊數+歐拉回路)

http 道路 遇到 連通塊 ems ble define ant trip 註意 題目鏈接:http://acm.hdu.edu.cn/showproblem.php?pid=3018 題目大意:有n個點,m條邊,人們希望走完所有的路,且每條道路只能走一遍。至少要將人們

最近公共祖先(LCA)的各種算法

host .cn 提取 模擬 最小值 以及 play 樹鏈剖分 pla 水一發題解。 我只是想存一下樹剖LCA的代碼...... 以洛谷上的這個模板為例:P3379 【模板】最近公共祖先(LCA) 1.樸素LCA 就像做模擬題一樣,先dfs找到基本信息:每個節點的父親、深度

HDU 1213 How Many Tables(強連通分量)

Today is Ignatius' birthday. He invites a lot of friends. Now it's dinner time. Ignatius wants to know how many tables he needs at least. You have to

hdu1232(強連通)

Problem Description 某省調查城鎮交通狀況,得到現有城鎮道路統計表,表中列出了每條道路直接連通的城鎮。省政府“暢通工程”的目標是使全省任何兩個城鎮間都可以實現交通(但不一定有直接的道路相連,只要互相間接通過道路可達即可)。問最少還需要建設多少條道路?   

最近公共祖先(LCA)的三種方法總結(Tarjan/倍增/樹鏈剖分)

以模板題目poj1330為例   Description A rooted tree is a well-known data structure in computer science and engineering. An example is shown below:

聯通塊個數【洛谷P1197】

傳送門:https://www.luogu.org/problemnew/show/P1197 並查集求聯通塊個數。 這個題是每摧毀一個點求一次聯通塊的個數,並查集不容易維護這種摧毀更新的,相反的,並查集可以很好的維護每安裝一個點更新一次這種問題。摧毀和安裝是對立的,既然按順序摧毀,我們就逆

Tarjan離線演算法最近公共祖先(LCA)

轉自: arjan離線演算法求LCA介紹      前言:首先,本人搞懂Tarjan求最近公共祖先(LCA),也是瀏覽了大量其他網友大牛的文章,若是看了本文仍未弄懂的,可以嘗試自己做一下模板題(裸題)HDU2586,自己用資料去感受一下,或者可以換篇文章再看,或許他的

HDU1856(最大集合)

有比較說明一點經驗:求最大值有時候不需要把資料求出來後遍歷。 注意:最大值的求解和比較的順序沒有關係,所以可以一邊求出資料,一邊進行比較。【即用設定全域性變數maxp的方法解決】 省去最後遍歷的步驟。  #include<iostream> #include

藍橋杯歷屆試題 危險係數(dfs或者無向圖關於兩點的割點個數)

Description 抗日戰爭時期,冀中平原的地道戰曾發揮重要作用。 地道的多個站點間有通道連線,形成了龐大的網路。但也有隱患,當敵人發現了某個站點後,其它站點間可能因此會失去聯絡。 我們來定義一個危險係數DF(x,y): 對於兩個站點x和y (x != y), 如果能找到一個站點z,當

用於最近公共祖先(LCA)的 Tarjan演算法–以POJ1986為例(轉)

給定有向無環圖(就是樹,不一定有沒有根),給定點U,V,找出點R,保證點R是U,V的公共祖先,且深度最深;或者理解為R離這兩個點的距離之和最小.如何找出R呢? 最一般的演算法是DFS(DFS本是深度優先搜尋,在這裡姑且把深度優先遍歷也叫做DFS,其實是

洛谷P2661 資訊傳遞(帶權有向圖最小環)

題目描述有n個同學(編號為1到n)正在玩一個資訊傳遞的遊戲。在遊戲裡每人都有一個固定的資訊傳遞物件,其中,編號為i的同學的資訊傳遞物件是編號為Ti同學。遊戲開始時,每人都只知道自己的生日。之後每一輪中,所有人會同時將自己當前所知的生日資訊告訴各自的資訊傳遞物件(注意:可能有人

最近公共祖先和所有祖先

#include "btree.cpp" //二叉鏈的基本運算 #include<iostream> using namespace std; bool allAncestor(BTNo

帶權最環

/* 把每個同學看成一個點,資訊的傳遞就是在他們之間連有向邊,遊戲輪數就是求最小環。 圖論求最小環,我在裡面看到了並查集。 假如說資訊由A傳遞給B,那麼就連一條由A指向B的邊,同時更新A的父節點,A到它的父節點的路徑長也就是B到它的父節點的路徑長+1。 這樣我們就建立

一般二叉樹最近公共祖先(最簡單的程式碼)

當遍歷到一個root點的時候, 1.判斷root是不是null如果root為null,那麼就無所謂祖先節點,直接返回null就好了 2.如果root的左子樹存在p,右子樹存在q,那麼root肯定就是最近祖先 3.如果pq都在root的左子樹,那麼就需要遞迴

集合個數和每個集合中的元素個數

思路:維護一個數組,代表以某個結點為根的樹的結點數目,初始化為全1。在合併兩個集合時,將秩較小的集合的元素數目加到秩較大的集合上。這裡需要注意一下,就是Union過程處理兩個祖先相同的結點,此時實際上沒有真正的合併這兩個結點,所以不需要更新集合的元素數目。至於統計集合個數就

3.19 Tarjan演算法與解決二叉樹節點間最近公共祖先的批量查詢問題

【題目】:   如下的Node類是標準的二叉樹節點結構: 1 public class Node{ 2 public int value; 3 public Node left; 4 public Node right; 5 6 pu

最近公共祖先

 #include<stdio.h> #include<cstdlib> #include<iostream> #include<cstdio> #include<vector> #include<cstring> #include<