您的位置:首页 > 其它

WOJ校赛 Problem 1542 - F - Countries 并查集+离散化+Floyd

2014-04-01 17:10 302 查看
Description

There are n countries at planet X on which Xiao Ming was born.

Some countries, which have been sharing fine bilateral relations, form a coalition and thus all of their citizens will benefit from a policy for which all the travels between these countries will become totally free.

But it is not easy to travel between countries distributed in different coalitions. If possible, it must cost some money called YZB(yu zhou bi) which is always positive.

Help Xiao Ming determine the minimum cost between countries.

Input

The input consists of one or more test cases.

First line of each test case consists two integers n and m. (1<=n<=10^5, 1<=m<=10^5)

Each of the following m lines contains: x y c, and c indicating the YZB traveling from x to y or from y to x. If it equals to zero, that means x and y are in the same coalition. (1<=x, y<=n, 0<=c<=10^9)

You can assume that there are no more than one road between two countries.

Then the next line contains an integer q, the number of queries.(1<=q<=200)

Each of the following q lines contains: x y. (1<=x, y<=n)

It is guaranteed that there are no more 200 coalitions.

Input is terminated by a value of zero (0) for n.

Output

For each test case, output each query in a line. If it is impossible, output “-1”.

Sample Input

6 5

1 2 0

2 4 1

3 5 0

1 4 1

1 6 2

3

4 2

1 3

4 6

0

Sample Output

1

-1

3

/*并查集带状态压缩,但是改成p[i]就会WA*/
/*AC*/
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>

using namespace std;

const int INF = (int)1e9 + 7;
const int MAXN = 100005;
const int MAXM = 100005;
int p[MAXN], u[MAXM], v[MAXM], w[MAXM], d[205][205], dir[MAXN];

int findset(int x) {
    if (p[x] == x)
        return x;
    else
        return p[x] = findset(p[x]);
}

void unionset(int x, int y) {
    int u = findset(x);
    int v = findset(y);
    if (u != v)
        p[u] = v;
}

void Floyd(int n) {
    for (int k = 0; k < n; k++)
        for (int i = 0; i < n; i++)
            for (int j = 0; j < n; j++)
                if (d[i][k] < INF && d[k][j] < INF)
                    if (d[i][j] > d[i][k] + d[k][j])
                        d[i][j] = d[i][k] + d[k][j];
}

int main() {
    int n, m, x, y, q;
    while (scanf("%d", &n) == 1 && n) {
        int cnt = 0;
        scanf("%d", &m);
        for (int i = 0; i < MAXN; i++)
            p[i] = i;
        for (int i = 0; i < 205; i++)
            for (int j = 0; j < 205; j++) {
                if (i == j)
                    d[i][j] = 0;
                else
                    d[i][j] = INF;
            }
        for (int i = 0; i < m; i++) {
            cin >> u[i] >> v[i] >> w[i];
            if (w[i] == 0)
                unionset(u[i], v[i]);
        }
        for (int i = 0; i < n; i++)
            if (p[i] == i) {
                dir[i] = cnt;
                cnt++;
            }
        for (int i = 0; i < n; i++)
            if (p[i] != i) {
            int x = findset(i);
            //int x = p[i];
            dir[i] = dir[x];
            }
        for (int i = 0; i < m; i++) {
            x = findset(u[i]);
            y = findset(v[i]);
            //x = p[u[i]];
            //y = p[v[i]];
            if (x != y) {
                int a = dir[x];
                int b = dir[y];
                if (w[i] < d[a][b])
                    d[a][b] = d[b][a] = w[i];//重新走一遍之前读进来的边,建好新图。
            }
        }
        Floyd(cnt);
        scanf("%d", &q);
        for (int i = 1; i <= q; i++) {
            scanf("%d%d", &x, &y);
            int u = findset(x);
            int v = findset(y);
            //int u = p[x];
            //int v = p[y];
            if (u == v) {
                printf("0\n");
                continue;
            }
            int r = dir[u];
            int s = dir[v];
            if (d[r][s] == INF)
                printf("-1\n");
            else
                printf("%d\n", d[r][s]);
        }
    }
    return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: