经常更新新边时,检查是否连接了两个节点

时间:2015-07-25 10:00:50

标签: algorithm depth-first-search

人们在社交网络中相互联系。人I和人J之间的联系表示为C I J.当属于不同社区的两个人联系时,净效应是我和J所属的两个社区的合并。 你的任务是找出两个人是否属于同一个群体。

输入格式

社交网络上的总人数(N) 查询

C I J,连接I和J

Q K L,查询社区以查明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 个答案:

答案 0 :(得分:0)

我认为您的数据结构效率低下,您不应该拥有同一网络的2份副本。以下是使用Map和多个Set的示例。每个Set对应一个网络,而Map则表示节点(密钥)和网络(值)之间的对应关系。

虽然在我的答案结尾处提供了整个代码,但我会详细介绍这里的两个主要方法(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代替{{1} }。

<强>伊辛

HashMap

好的,所以这个很简单,要检查连接,检查private static boolean isIn (int a, int b) { return nodes.get(a).contains(b) ; } 的网络是否包含节点a。请注意,b返回nodes.get(a)的网络,您还可以查看a

<强> addConnection

nodes.get(b).contains(a)

再次,琐碎:

  1. 您检索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)) ; } } }
  2. 的网络
  3. 您将b网络中的所有节点添加到b的网络。
  4. ab)旧网络中的Foreach节点,包括nodes.get(i) == setB本身,您将网络设置为新网络。
  5. 整个代码(取消注释):

    b

答案 1 :(得分:0)

您可以使用union-find数据结构。为此, SharedPreferences prefs = getSharedPreferences("com.mobileapp.smartapplocker", MODE_PRIVATE); boolean switchState = pref.getBoolean("service_status", false); if(switchState){ //Do your work for service is selected on } else { //Code for service off } union()方法实际上都是O(1)。

使用人数初始化结构。

如果您遇到find()连接,请致电C i j

如果您遇到查询union(i, j),请输出Q i j