HLG 1360 Leyni的国家III (并查集)

链接:http://acm.hrbust.edu.cn/index.php?m=ProblemSet&a=showProblem&problem_id=1360

Description

Leyni经过了若干年的征战,终于建立了自己的国家,这个国家包含n个城市,编号为1n,而且这些城市之间存在m条双向通行的道路。不过Leyni的国家刚刚建立,所以他对每一条道路定义了道路警戒级别,由高到低分别为,a级,b级,c级。接下来,每条路径的路径警戒级别就等于这条路径所经过的所有道路的最高警戒级别;每两个城市之间的城际警戒级别就等于这两个城市之间的所有路径中的最低路径警戒级别。

现在,Leyni告诉了你所有道路的道路警戒级别,他想知道某些城市之间的城际警戒级别,请你帮助他!

Input

本题有多组测试数据,输入的第一行是一个整数T代表着测试数据的数量,接下来是T组测试数据。

对于每组测试数据:

1 包含三个以空格分隔的整数nmq (1 ≤ n ≤ 105, 0 ≤ m, q ≤ 106)

2 .. m + 1 每行包含一对整数uv (1 ≤ u, v ≤ n, u ≠ v) 与一个字母x ("a", "b", "c"之一)代表着城市uv之间存在着一条警戒级别为x的道路。

注:输入数据保证每对城市之间最多只存在一条道路。

m + 2 .. m + 1 + q 每行包含一对整数uv (1 ≤ u, v ≤ n, , u ≠ v) 代表着Leyni要查询城市uv之间的城际警戒级别。

Output

对于每组测试数据:

1 .. q 请针对每次Leyni的查询按照其查询的顺序输出两个城市之间的城际警戒级别,如果两城市之间不存在路径,则输出-1

Sample Input

1

4 4 4

1 2 c

2 3 a

3 4 b

2 4 c

1 2

2 3

3 4

1 4

Sample Output

c

b

b

c

This Code Submitted By Kesha:

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#define MAXN 100000+10
using namespace std;

int father[3][MAXN];

void Make_Set(int n)  //初始化,每一个节点对应自身的父亲节点
{
    for(int i=0; i<3; i++) {
        for(int j=1; j<=n; j++) {
            father[i][j] = j;
        }
    }
}

int Find_Set(int x, int v)  //查找父亲节点
{
    if(x != father[v][x]) {
        father[v][x] = Find_Set(father[v][x], v); //状态压缩
    }
    return father[v][x];
}

void Union_Set(int x, int y, int v)  //节点的结合
{
    x = Find_Set(x, v);
    y = Find_Set(y, v);
    if(x == y) return ;
    if(x > y) father[v][x] = father[v][y];
    else father[v][y] = father[v][x];
}

void solve(int Mc, int Md)
{
    if(Find_Set(Mc, 2) == Find_Set(Md, 2)) puts("c");
    else if(Find_Set(Mc, 1) == Find_Set(Md, 1)) puts("b");
    else if(Find_Set(Mc, 0) == Find_Set(Md, 0)) puts("a");
    else puts("-1");
}

int main()
{
    int cas, n, m, q;
    scanf("%d", &cas);

    while(cas--) {
        scanf("%d %d %d", &n, &m, &q);
        Make_Set(n);
        int Mc, Md; char s[2];
        for(int i=0; i<m; i++) {
            scanf("%d %d %s", &Mc, &Md, s);
            int flag = s[0] - 'a';
            Union_Set(Mc, Md, flag);
            if(flag == 0) {
                Union_Set(Find_Set(Mc, 1), Find_Set(Md, 1), 0);
                Union_Set(Find_Set(Mc, 2), Find_Set(Md, 2), 0);
            }else if(flag == 1) {
                Union_Set(Find_Set(Mc, 0), Md, 0);
                Union_Set(Find_Set(Md, 0), Mc, 0);
                Union_Set(Find_Set(Mc, 2), Find_Set(Md, 2), 1);
            }else {
                Union_Set(Find_Set(Mc, 0), Md, 0);
                Union_Set(Find_Set(Md, 0), Mc, 0);
                Union_Set(Find_Set(Mc, 1), Md, 1);
                Union_Set(Find_Set(Md, 1), Mc, 1);
            }
        }
        for(int i=0; i<q; i++) {
            scanf("%d %d", &Mc, &Md);
            solve(Mc, Md);
        }
    }
    return 0;
}

后续解法待续。。。


你可能感兴趣的:(并查集,状态压缩)