• HDU 5441 离线处理 + 并查集


    题意:给n个节点m条带权值边的无向图。然后q个问题,每次询问点对的数目,点对需要满足的条件是:1)连通;2)其路径的最大权值不能超过询问值。

    分析:如果没次询问一次,dfs一次,很可能超时,因此可以用并查集。离线处理,把边按权值排序,把问题按大小排序。然后离线的过程就是不断向图中加边的过程。

    比如样例如下:

    然后离线处理,排完序后将会是一条一条的加边:问题也排了序,因此是个累加过程。。。

     1 #include <cstdio>
     2 #include <iostream>
     3 #include <sstream>
     4 #include <cmath>
     5 #include <cstring>
     6 #include <cstdlib>
     7 #include <string>
     8 #include <vector>
     9 #include <map>
    10 #include <set>
    11 #include <queue>
    12 #include <stack>
    13 #include <algorithm>
    14 #define ll long long
    15 #define mem(m, a) memset(m, a, sizeof(m))
    16 #define repu(i, a, b) for(int i = a; i < b; i++)
    17 #define maxn 100005
    18 const double PI=-acos(-1.0);
    19 using namespace std;
    20 struct node
    21 {
    22     int x,y,z;
    23     bool operator < (const node &a) const
    24     {
    25         return z < a.z;
    26     }
    27 } e[maxn];
    28 struct Q
    29 {
    30     int w,id;
    31     bool operator < (const Q &a) const
    32     {
    33         return w < a.w;
    34     }
    35 } q[maxn];
    36 int ans[maxn];
    37 int fa[maxn],num[maxn];
    38 int find_set(int x)
    39 {
    40     if(x==fa[x])
    41         return fa[x];
    42     else
    43         return fa[x]=find_set(fa[x]);
    44 }
    45 int main()
    46 {
    47     int n,m,k,t;
    48     scanf("%d",&t);
    49     while(t--)
    50     {
    51         scanf("%d%d%d",&n,&m,&k);
    52         repu(i,0,m)
    53         scanf("%d%d%d",&e[i].x,&e[i].y,&e[i].z);
    54         repu(i,0,k)
    55         scanf("%d",&q[i].w),q[i].id=i;
    56         sort(e,e+m);
    57         sort(q,q+k);
    58         repu(i,1,1+n)
    59         fa[i]=i,num[i]=1;
    60         int cnt=0,j=0;
    61         repu(i,0,k)
    62         {
    63             while(j<m&&e[j].z<=q[i].w)
    64             {
    65                 int x=find_set(e[j].x);
    66                 int y=find_set(e[j].y);///找各自的所属的集合编号
    67                 if(x != y)
    68                 {
    69                     cnt += num[x]*num[y];///各自集合的数目相乘
    70                     fa[x] = y;///因为已经统一集合了
    71                     num[y] += num[x];///y集合的数目就可以直接加上x的数目
    72                 }
    73                 j++;
    74             }
    75             ans[q[i].id] = 2*cnt;
    76         }
    77         repu(i,0,k)
    78         printf("%d
    ",ans[i]);
    79     }
    80     return 0;
    81 }
    View Code
  • 相关阅读:
    第十七周OJ-重复字符串
    第十七周项目6-学生成绩统计(一)
    第十七周项目5-玩日期时间
    python面试题(三)列表操作
    python面试题(二)字符串常用函数
    python面试题(-)可变数据类型与不可变数据类型
    Cisco packet tracer6.0下的网络工程实训
    Cisco packet tracer下dhcp的配置的vlan的应用
    python的自定义函数
    git学习二
  • 原文地址:https://www.cnblogs.com/ACMERY/p/4808889.html
Copyright © 2020-2023  润新知