Sicily 1876/1949. Basic Graph Problem

这是一个关于图论的基本问题,涉及判断给定图中任意两个节点是否直接或间接相连。输入包括节点数量、节点编号、边的数量及连接信息,以及查询对的数量。输出是对每个查询对是否连通的判断。样例输入展示了如何根据输入信息确定节点间的连接关系。
摘要由CSDN通过智能技术生成

1876. Basic Graph Problem

Constraints

Time Limit: 5 secs, Memory Limit: 32 MB

Description

Graph theory is an interesting science and applied in many areas. We can always construct a graph model when we have a complicated problem to consider. With the model, we can simplify the problem and know what and how we should do. There are many well-known problems in graph theory, such as Hamilton Cycle, traveling salesman problem, postman problem. etc. Oh, god, all of them seems too difficult to think about for most college students. Don’t worry, in this problem we just need to consider a basic problem: the connectivity of a graph (Aha, is it easy enough for you ^_^)
We denoted a graph G as (V, E),V is the set of all the nodes in G, and N=|V| is the number of nodes in G.E is the set of all the edges in G, An edge can be denoted by two nodes (a1,a2),that means node a1 and node a2 are connected by one edge.
Now the problem is: Given a graph G, could you tell whether any of two nodes are connected (both directed and undirected).

Input

There are many test data in the input, a test data is defined as follow:
The first line of test data contains an integer n (1<=n<=100000), the number of nodes of G
It’s followed by n different integers, one integer Ai (1<=Ai<=n, 1<=i<=n)per line. (We use integer 1 to n to denote the nodes of G)
n
A1 (1<= A1<=n)
A2 (1<= A2<=n)

An (1<= An<=n)

The next line contains an integer m (1<=m<=500000).Following this are m lines, describing the edges of G. Each line contains two integers Si and Ei (1<=Si<=n,1<=Ei<=n,
,Si<Ei 1<=i<=m)
m
S1 E1 (1<=S1<=n,1<=E1<=n,S1<E1)
S2 E2 (1<=S2<=n,1<=E2<=n,S2<E2)
….
Sm Em (1<=Sm<=n,1<=Em<=n,Sm<Em)
For each i (1<=i<=m), you should find the minimal number Amin =min{ As1, As2…. Ae1,} and maximal number Amax =max{ As1, As2…. Ae1} from the n different integers inputted before in the range of [Si, Ei], and then we can get an information that Amin and Amax are connected by one edge directly in G

The next line contains an integer k (1<=k<=100000), followed by k queries
K
u1 v1 (1<=u1<=n, 1<= v1<=n)
u2 v2 (1<=u2<=n, 1<= v2<=n)
….
uk vk (1<=uk<=n, 1<= vk<=n)
For each i (1<=i<=k) , you should answer whether node ui and node vi is connected (both directed and undirected). 
You can assume that any node is always connected by itself, and there may be many edges between any two nodes.
Input is ended by EOF.

Output

For each test data, first display the case number (starts with 1 and increases sequentially), and then you should output k lines. For each line , you should output “YES “on the ith line if node ui and node vi is connected (both directed and undirected)in the input ,or “NO” otherwise. Output should be separated by one blank line.

Sample Input

3
3
1
2
1
1 2
5
1 3
3 1
2 2
1 2
2 3

5
2
3
5
4
1
3
2 3
3 5
1 2
3
3 1
5 1
4 5

Sample Output

CASE 1
YES
YES
YES
NO
NO

CASE 2
YES
YES
NO

Hint

Here is the explanation of the last sample input. There are 5 nodes and the input order is 2 3 5 4 1.There are 3 edges: Since the 2 nd and the 3th number in the input is {3 , 5},so the minimal number is 3 and maximal number is 5,and we know that node 3 and node 5 is connected directed. Similarly, the 3th ,4 th and 5 th number in the input is {5, 4, 1}, the minimal number is 1 and the maximal number is 5. That means node 1 and node 5 is also connected by a edge. Likewise we can get the information that node 2 is connected to node 3 from input. So that node 1 and node 3 are connected undirected, node5 and node1 are connected directed, node5 and node4 are not connected.

// Problem#: 1876
// Submission#: 3589915
// The source code is licensed under Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License
// URI: http://creativecommons.org/licenses/by-nc-sa/3.0/
// All Copyright reserved by Informatic Lab of Sun Yat-sen University
#include <stdio.h>

const int MAXV = 101100;

int n, m, k;

struct node {
    int min, max;
};

node arr[MAXV];
int input[MAXV];
int c;
int parent[MAXV];

void buildtree(int s, int e,int & maximal, int & minimal) {
    if (e - s + 1 <= 0) {
        maximal = minimal = -1;
        return;
    }
    if (e - s + 1 == 1) {
        maximal = minimal = input[e];
        return;
    }
    if (e - s + 1 == 2) {
        maximal = input[s] > input[e] ? input[s] : input[e];
        minimal = input[s] > input[e] ? input[e] : input[s];
        return;
    }
    int temp = (s + e) / 2;
    arr[temp].max = input[temp];
    arr[temp].min = input[temp];
    int i, j;
    buildtree(s, temp - 1, i, j);
    if (i >= 0 && j >= 0) {
        if (i > arr[temp].max) arr[temp].max = i;
        if (j < arr[temp].min) arr[temp].min = j;
    }
    buildtree(temp + 1, e, i, j);
    if (i >= 0 && j >= 0) {
        if (i > arr[temp].max) arr[temp].max = i;
        if (j < arr[temp].min) arr[temp].min = j;
    }
    maximal = arr[temp].max;
    minimal = arr[temp].min;
}

void init() {
    int i, j;
    buildtree(0, n - 1, i, j);
}

void searchtree(int s, int e, int & maximal, int & minimal, int u, int v) {
    if (e - s + 1 <= 0) {
        maximal = minimal = -1;
        return;
    }
    if (s == u && v == e) {
        if (e - s + 1 <= 0) {
            maximal = minimal = -1;
            return;
        }
        if (e - s + 1 == 1) {
            maximal = minimal = input[e];
            return;
        }
        if (e - s + 1 == 2) {
            maximal = input[s] > input[e] ? input[s] : input[e];
            minimal = input[s] > input[e] ? input[e] : input[s];
            return;
        }
        maximal = arr[(s + e) / 2].max;
        minimal = arr[(s + e) / 2].min;
        return;
    }
    int temp = (s + e) / 2;
    int i, j;
    if (u <= temp && temp <= v) {
        maximal = input[temp];
        minimal = input[temp];
        if (u <= temp - 1) {
            searchtree(s, temp - 1, i, j, u, temp - 1);
            if (i > maximal) maximal = i;
            if (j >= 0 && j < minimal) minimal = j;
        }
        if (v >= temp + 1) {
            searchtree(temp + 1, e, i, j, temp + 1, v);
            if (i > maximal) maximal = i;
            if (j >= 0 && j < minimal) minimal = j;
        }
        return;
    }
    if (u > temp) {
        searchtree(temp + 1, e, maximal, minimal, u, v);
        return;
    }
    searchtree(s, temp - 1, maximal, minimal, u, v);
}

int find(int a) {
    int i = a;
    while (parent[a] >= 0) a = parent[a];
    while (i != a) {
        int temp = parent[i];
        parent[i] = a;
        i = temp;
    }
    return a;
}

void unionset(int a, int b) {
    int i = find(a), j = find(b);
    if (i == j) return;
    if (i < j) {
        parent[j] = i;
        parent[i]--;
    } else {
        parent[i] = j;
        parent[j]--;
    }
}

void process() {
    int i;
    if (c != 0) printf("\n");
    c++;
    printf("CASE %d\n", c);
    for (i = 0; i < n; i++) {
        scanf("%d", input + i);
        input[i]--;
        parent[i] = -1;
    }
    init();
    scanf("%d", &m);
    int u, v;
    for (i = 0; i < m; i++) {
        scanf("%d%d", &u, &v);
        u--;
        v--;
        searchtree(0, n - 1, u, v, u, v);
        unionset(u, v);
    }
    scanf("%d", &k);
    for (i = 0; i < k; i++) {
        scanf("%d%d", &u, &v);
        u--;
        v--;
        if (find(u) == find(v)) printf("YES\n");
        else printf("NO\n");
    }
}

int main() {
    while (scanf("%d", &n) != EOF) process();
    return 0;
}                                 


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值