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\n",ans[i]);
79     }
80     return 0;
81 }

时间: 2024-08-02 02:48:02

HDU 5441 离线处理 + 并查集的相关文章

Hdu 5441 Travel(并查集)

题目地址:http://acm.hdu.edu.cn/showproblem.php?pid=5441 思路:离线处理.将边权值按从小到大排序,查询标号后按照从小到大排序.对于每次查询,依次将比当前查询值小的边加入并查集.对于两个符合条件即将合并的连通块增加答案个数num[x]*num[y]*2 .合并:fa[x]=y; num[y]+=num[x]; .最后依次输出结果即可. #include<cstdio> #include<cstring> #include<iostr

HDU 5441 Travel(并查集+统计节点个数)

http://acm.hdu.edu.cn/showproblem.php?pid=5441 题意:给出一个图,每条边有一个距离,现在有多个询问,每个询问有一个距离值d,对于每一个询问,计算出有多少点对(x,y)使得在x到y的路径上没有一条边的距离大于d. 思路:只要边距离小于d,那就是可行的,直接加入并查集来维护.并查集需要维护一下树的节点个数. 将边和询问都排序离线处理. 1 #include<iostream> 2 #include<cstdio> 3 #include<

hdu 5441 Travel 离线操作+并查集

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5441 题意:给出一张图,有n个点,m条带权边,每次询问给出一个值val,要求删除权值>val的所有边.然后每次询问求多少个点对相连,ab和ba算成两个点对. 思路: 把每条边的权值按照从小到大排序,把每个询问记录下来,按照从小到大排序. 初始图没有边.然后按照询问加入边.对于每个询问,除了已经加入的边,再加入权值比它小的边. 然后用并查集求得每次加一条边后新产生的点对. 用一个数组cnt[i],来记

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小的开始遍历,然后去判断有几个连通块,在连通块中计数,用一个数组即可,运用排列组合的知识可以知

HDU 5441——Travel——————【并查集+二分查界限】

Travel Time Limit: 1500/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)Total Submission(s): 1313    Accepted Submission(s): 472 Problem Description Jack likes to travel around the world, but he doesn’t like to wait. Now, he is tr

hdu 3234 Exclusive-OR (并查集+异或性质)

Exclusive-OR Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 2177    Accepted Submission(s): 603 Problem Description You are not given n non-negative integers X0, X1, ..., Xn-1 less than 220 ,

HDU 4496 D-City (并查集)

题意:给你n个点m条边,问删除前i条边后有多少个连通分块. 思路:从后往前操作,从后往前添加i条边等于添加完m条边后删掉前m-i条边,可知刚开始没有边,所以sum[m]=n; #include <stdio.h> #include <iostream> #include <algorithm> #include <string.h> #include <queue> #include <math.h> #define M 100010

hdu 1811Rank of Tetris (并查集 + 拓扑排序)

1 /* 2 题意:这些信息可能有三种情况,分别是"A > B","A = B","A < B",分别表示A的Rating高于B,等于B,小于B. 3 4 现在Lele并不是让你来帮他制作这个高手榜,他只是想知道,根据这些信息是否能够确定出这个高手榜,是的话就输出"OK". 5 否则就请你判断出错的原因,到底是因为信息不完全(输出"UNCERTAIN"),还是因为这些信息中包含冲突(输出&quo

URAL1671 Anansi&#39;s Cobweb(离线做 + 并查集)

传送门 大意:给出一个无向图,删除Q条边,每删除一次就询问一次目前的连通块的数目. 思路:离线搞, 把删边转换为加边,每加一次边,若两个顶点不连通就用并查集把着这两个连通块合并. 代码: #include<cstdio> #include<cstring> #include<algorithm> #define MAXN 100005 using namespace std; int n, m, q; int s[MAXN], t[MAXN]; int ban[MAXN