zoukankan      html  css  js  c++  java
  • HDU 5441 Travel (并查集+数学+计数)

    题意:给你一个带权的无向图,然后q(q≤5000)次询问,问有多少对城市(城市对(u,v)与(v,u)算不同的城市对,而且u≠v)之间的边的长度不超过d(如果城市u到城市v途经城市w,

    那么需要城市u到城市w的长度e1≤d,同时城市w到城市v的长度e2≤d)。

    析:一开始的时候,题意都读错了,怎么看都不对,原来是只要最大的d小于等于x就可以,过了好几天才知道是这样。。。。。

    这个题是并查集的应用,先从d小的开始遍历,然后去判断有几个连通块,在连通块中计数,用一个数组即可,运用排列组合的知识可以知道一个连通块中, 一共有

    n * (n-1)对,然后不断更新连通块中结点的数量即可,先排序再输出。其实并不难。要注意加结点的时候,谁是谁是父结点,这个是很重要的。

    代码如下:

    #pragma comment(linker, "/STACK:1024000000,1024000000")
    #include <cstdio>
    #include <string>
    #include <cstdlib>
    #include <cmath>
    #include <iostream>
    #include <cstring>
    #include <set>
    #include <queue>
    #include <algorithm>
    #include <vector>
    #include <map>
    #include <cctype>
    using namespace std ;
    
    typedef long long LL;
    typedef pair<int, int> P;
    const int INF = 0x3f3f3f3f;
    const double inf = 0x3f3f3f3f3f3f3f;
    const double eps = 1e-8;
    const int maxn = 2e4 + 5;
    const int mod = 1e9 + 7;
    const int dr[] = {0, 0, -1, 1};
    const int dc[] = {-1, 1, 0, 0};
    int n, m;
    inline bool is_in(int r, int c){
        return r >= 0 && r < n && c >= 0 && c < m;
    }
    struct node{
        int u, v, w;
        bool operator < (const node &p) const{
            return w < p.w;
        }
    };
    node a[maxn*5];
    struct node1{
        int id, w;
        bool operator < (const node1 &p) const{
            return w < p.w;
        }
    };
    node1 x[5005];
    int p[maxn], w[maxn], ans[maxn];
    
    int Find(int x){  return x == p[x] ? x : p[x] = Find(p[x]); }
    
    int main(){
        int T;  cin >> T;
        while(T--){
            int q;
            scanf("%d %d %d", &n, &m, &q);
            for(int i = 1; i <= n; ++i)  p[i] = i, w[i] = 1;
            for(int i = 0; i < m; ++i)  scanf("%d %d %d", &a[i].u, &a[i].v, &a[i].w);
            for(int i = 0; i < q; ++i)  scanf("%d", &x[i].w), x[i].id = i;
            sort(a, a+m);
            sort(x, x+q);
    
            int j = 0, num = 0;
            for(int i = 0; i < q; ++i){
                while(j < m && a[j].w <= x[i].w){
                    int xx = Find(a[j].u);
                    int yy = Find(a[j].v);
                    if(xx != yy){
                        num -= w[xx] * (w[xx]-1) + w[yy] * (w[yy]-1);
                        w[xx] += w[yy];
                        w[yy] = 0;
                        num += w[xx] * (w[xx]-1);
                        p[yy] = xx;//注意父结点的选取
                    }
                    ++j;
                }
                ans[x[i].id] = num;
            }
    
            for(int i = 0; i < q; ++i)
                printf("%d
    ", ans[i]);
        }
        return 0;
    }
    
  • 相关阅读:
    PHP Session保存到数据库
    PHP empty操作记录
    jquery 捕捉回车事件
    滚动条样式设计IE支持
    PHP 常用字符串处理代码片段
    JQuery选择符分类汇总
    php 操作数组 (合并,拆分,追加,查找,删除等)
    救命的PHP代码
    耍耍
    标准国家代码
  • 原文地址:https://www.cnblogs.com/dwtfukgv/p/5742609.html
Copyright © 2011-2022 走看看