HDU3938 Portal 并查集

10 10 10
7 2 1
6 8 3
4 5 8
5 8 2
2 8 9
6 4 5
2 1 5
8 10 5
7 3 7
7 8 8
10 //查询长度
6
1
5
9
1
8
2
7
6
#include 
#include 
#include 
#include 

using namespace std;

const int M = 10005;

/*
本题题意有必要说一下, 给出一系列查询长度, 要求你找出任意两点间的最长边小于等于给出的查询
长度, 做法是对给出的边排序,具体看代码, 我也是看了别人写的才明白题意的。
*/
struct node {

    int x;
    int y;
    int d;

}edge[M*5];

struct Node {

    int len;
    int ans;
    int id;

}query[M];

int p[M];
int sum[M];
int n, m, q;

bool cmp(node p1, node p2) {

    return p1.d < p2.d;
}

bool cmp1(Node p1, Node p2) {

    return p1.len < p2.len;
}

bool cmp2(Node p1, Node p2) {

    return p1.id < p2.id;
}

void init() {

    for(int i = 1; i <= n; i++) {

        p[i] = i;
        sum[i] = 1;
    }
}

int Find(int a) {

    return a == p[a] ? a : p[a] = Find(p[a]);
}

int Union(int a, int b) {

    a = Find(a);
    b = Find(b);
    if(a == b)
        return 0;
    else {

        p[a] = b;
        int temp = sum[a]*sum[b];
        sum[b] += sum[a];
        return temp;
    }
}

int main()
{
    while(scanf("%d%d%d", &n, &m, &q) != EOF) {

        init();
        for(int i = 0; i < m; i++) {

            scanf("%d%d%d", &edge[i].x, &edge[i].y, &edge[i].d);
        }
        for(int i = 0; i < q; i++) {

            scanf("%d", &query[i].len);
            query[i].id = i;
            query[i].ans = 0;
        }
        sort(edge, edge+ m, cmp);
        sort(query, query+q, cmp1);
        int cnt = 0;
        for(int i = 0; i < q; i++) {

            while(edge[cnt].d <= query[i].len && cnt < m) {

                query[i].ans += Union(edge[cnt].x, edge[cnt].y);
                    cnt++;
            }
            if(i > 0)
                query[i].ans += query[i-1].ans;
        }
        sort(query, query+q, cmp2);

        for(int i = 0; i < q; i++) {

            printf("%d\n", query[i].ans);
        }
    }
    return 0;
}

你可能感兴趣的:(并查集)