簡體   English   中英

頻繁更新新邊緣時檢查是否連接了兩個節點

[英]Check if two nodes are connected when updating new edges frequently

人們在社交網絡中相互聯系。 人I和人J之間的聯系表示為CIJ。當兩個屬於不同社區的人連接時,最終結果是我和J所屬的兩個社區合並。 您的任務是找出兩個人是否在同一組中。

輸入格式

社交網絡上的總人數(N)個查詢

CIJ,連接I和J

QKL,查詢社區以找出K和L是否屬於相同的組-1表示輸入結束。

輸出格式

對於每個查詢Q,如果K和L在同一組中,則打印“是”,否則打印“否”。

樣本測試用例

5
C 1 2
Q 1 2
C 2 3
C 3 4
Q 1 2
Q 1 3
Q 3 2
Q 1 5

輸出量

Yes
Yes
Yes
Yes
No

所以我認為這是一個基本的深度優先搜索以找出兩個節點之間的鏈接..但是我超出了時間限制。

 public class isotope {
    static List<Integer>[] list;
    static boolean[] vis;
    static int end;

    public static void main(String[] args) {
        InputReader in = new InputReader(System.in);
        PrintWriter out = new PrintWriter(new OutputStreamWriter(System.out));
        solve(in, out);
        out.close();
    }

    static void solve(InputReader in, PrintWriter out) {
        int n = in.nextInt();
        list = new List[n + 1];
        for (int i = 0; i < list.length; i++) list[i] = new ArrayList<>();
        while (true) {
            String[] temp = in.readLine().split(" ");
            //System.out.println(Arrays.toString(temp));
            if (temp[0].equals("-1")) return;
            //System.out.println(temp[0]);
            if (temp[0].equals("C")) {
                int x = Integer.parseInt(temp[1]);
                int y = Integer.parseInt(temp[2]);
                list[x].add(y);
                list[y].add(x);
            } else if (temp[0].equals("Q")) {
                vis = new boolean[n + 1];
                int a = Integer.parseInt(temp[1]);
                int b = Integer.parseInt(temp[2]);

                end = b;
                if (depthfs(a)) out.println("Yes");
                else out.println("No");
            }
        }

    }

    depthfs(int start) {
        vis[start] = true;
        int k = 0;
        Stack<Integer> stk = new Stack<>();
        stk.push(start);
        while (!stk.isEmpty()) {
            int x = stk.pop();
            for (int i = 0; i < list[x].size(); i++) {

                //System.out.println("LIST "+list[x].get(i));
                //System.out.println(stk);//if(++k>10)return true;
                if (list[x].get(i) == end) {
                    //System.out.println("ANSWER IS "+end);
                    return true;
                } else if (!vis[list[x].get(i)]) {
                    vis[list[x].get(i)] = true;
                    stk.push(list[x].get(i));
                }
            }
        }
        return false;
    }

我認為您的數據結構效率很低,您不應該擁有同一網絡的2個副本。 這是一個使用Map和Multiple Set的示例。 每個Set對應於一個網絡,而Map則在節點(鍵)和網絡(值)之間進行對應。

雖然整個代碼都可以在我的答案末尾找到,但我將在這里詳細介紹2個主要方法( isInaddConnection ):

private static List <Set<Integer>> nodes ;

第一件事是使用初始網絡(每個節點在其自己的網絡中)初始化nodes 假設有N節點(您讀取的第一個值):

// Nodes number goes from 1 to N, not 0 to N - 1, but I don't want to deal with this
// so I will add a fake 0 node.
nodes = new ArrayList <Set <Integer>> () ;
for (int i = 0 ; i < N + 1 ; ++i) {
    Set <Integer> s = new HashSet <Integer> () ;
    s.add(i) ;
    nodes.add (s) ;
}

因此,這里的nodes.get(a)是節點a的網絡。 如果ab在同一網絡上,則我們有nodes.get(a) == nodes.get(b) ,請注意,這里我在談論指針相等, nodes.get(a)是同一對象(在內存中) )作為nodes.get(b)

注意:由於您一開始就知道節點總數,並且由於節點是按數字順序排列的,因此可以使用簡單的ArrayList代替HashMap

isIn

private static boolean isIn (int a, int b) {
    return nodes.get(a).contains(b) ;
}

好了,這很簡單,要檢查連接,請檢查a的網絡是否包含節點b 請記住, nodes.get(a)返回的網絡a ,你也可以查看nodes.get(b).contains(a)

addConnection

private static void addConnection (int a, int b) {
    Set <Integer> setB = nodes.get(b) ;
    nodes.get(a).addAll (setB) ;
    for (int i = 0 ; i < nodes.size() ; ++i) {
        if (nodes.get(i) == setB) {
            nodes.set(i, nodes.get(a)) ;
        }
    }
}

再次,瑣碎:

  1. 您檢索b的網絡。
  2. 您將b網絡中a所有節點添加到b網絡中。
  3. 對於舊網絡b中的foreach節點( nodes.get(i) == setB ),包括b本身,將網絡設置為新網絡。

整個代碼 (未注釋):

import java.io.IOException;
import java.io.OutputStreamWriter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Scanner;
import java.util.Set;

public class NetworkStuff1 {

    private static List <Set<Integer>> nodes ;

    private static boolean isIn (int a, int b) {
        return nodes.get(a).contains(b) ;
    }

    private static void addConnection (int a, int b) {
        Set <Integer> setB = nodes.get(b) ;
        nodes.get(a).addAll (setB) ;
        for (int i = 0 ; i < nodes.size() ; ++i) {
            if (nodes.get(i) == setB) {
                nodes.set(i, nodes.get(a)) ;
            }
        }
    }

    public static void solve (Scanner in, OutputStreamWriter out) throws IOException {
        int N = Integer.parseInt (in.nextLine()) ;
        // Nodes number goes from 1 to N, not 0 to N - 1, but I don't want to deal with this
        // so I add a useless 0 cell in my array.
        nodes = new ArrayList <Set <Integer>> () ;
        for (int i = 0 ; i < N + 1 ; ++i) {
            Set <Integer> s = new HashSet <Integer> () ;
            s.add(i) ;
            nodes.add (s) ;
        }
        while (true) {
            String[] tmp = in.nextLine().split(" ") ;
            if (tmp[0].equals("-1")) {
                break ;
            }
            if (tmp[0].equals("C")) {
                addConnection(Integer.parseInt (tmp[1]), Integer.parseInt (tmp[2])) ;
            }
            else if (tmp[0].equals("Q")){
                if (isIn (Integer.parseInt (tmp[1]), Integer.parseInt (tmp[2]))) {
                    System.out.println("Yes") ;
                }
                else {
                    System.out.println("No") ;
                }
            }
        }
    }

    /**
     * @param args
     * @throws IOException 
     */
    public static void main(String[] args) throws IOException {
        solve (new Scanner(System.in), new OutputStreamWriter(System.out)) ;
    }

}

您可以為此使用聯合查找數據結構。 為此, union()find()方法實際上都是O(1)。

用人數初始化結構。

如果遇到連接C ij ,請調用union(i, j)

如果遇到查詢Q ij ,則輸出find(i) == find(j)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM