HDU 5441 Travel 并查集

HDU 5441 Travel

题意:一张无向图,q个查询,对于每个x,有多少对点之间的路径中最长的一条路不大于x。

思路:比赛时王秋平写的,我补下题。这题也比较简单,将边排序,从小到大加到并查集,对查询也排序,从小到大对于每个查询把不大于x的边加到并查集,用cnt[y]记录以y为根的连通块有多少节点,那么在连通块发生 变化时,ans=2 * cnt[x] * cnt[y]

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <fstream>
 4 #include <algorithm>
 5 #include <cmath>
 6 #include <deque>
 7 #include <vector>
 8 #include <queue>
 9 #include <string>
10 #include <cstring>
11 #include <map>
12 #include <stack>
13 #include <set>
14 #define LL long long
15 #define eps 1e-8
16 #define INF 0x3f3f3f3f
17 #define MAXN 20005
18 #define MAXM 100005
19 #define MAXP 5005
20 using namespace std;
21 struct Edge{
22     int from, to, dist;
23     Edge(int from = 0, int to = 0, int dist = 0) :from(from), to(to), dist(dist)  {};
24 }edges[MAXM];
25 int father[MAXN], cnt[MAXN], res[MAXP];
26 struct Node{
27     int  x, pos;
28     Node(int x = 0, int pos = 0) :x(x), pos(pos){};
29 };
30 Node a[MAXP];
31 bool compare(Edge a, Edge b){
32     return  a.dist < b.dist;
33 }
34 bool comp(Node a, Node b){
35     return a.x < b.x;
36 }
37 int find(int x){
38     if (father[x] == x){
39         return x;
40     }
41     father[x] = find(father[x]);
42     return father[x];
43 }
44 int main()
45 {
46 #ifndef ONLINE_JUDGE
47     freopen("in.txt", "r", stdin);
48     //freopen("out.txt", "w", stdout);
49 #endif // OPEN_FILE
50     int T;
51     scanf("%d", &T);
52     int n, m, q;
53     while (T--){
54         scanf("%d%d%d", &n, &m, &q);
55         int x, y, z;
56         for (int i = 1; i <= m; i++){
57             scanf("%d%d%d", &x, &y, &z);
58             edges[i] = Edge(x, y, z);
59         }
60         sort(edges + 1, edges + m + 1, compare);
61         for (int i = 1; i <= q; i++){
62             scanf("%d", &a[i].x);
63             a[i].pos = i;
64         }
65         sort(a + 1, a + q + 1, comp);
66         for (int i = 1; i <= n; i++){
67             father[i] = i;
68             cnt[i] = 1;
69         }
70         int s = 1;
71         int ans = 0;
72         memset(res, 0, sizeof(res));
73         for (int i = 1; i <= q; i++){
74             for (int j = s; j <= m && edges[j].dist <= a[i].x; j++, s = j){
75                 int x = find(edges[j].from);
76                 int y = find(edges[j].to);
77                 if (x == y) continue;
78                 father[x] = y;
79                 ans += 2 * cnt[x] * cnt[y];
80                 cnt[y] += cnt[x];
81             }
82             res[a[i].pos] = ans;
83         }
84         for (int i = 1; i <= q; i++){
85             printf("%d\n", res[i]);
86         }
87     }
88 }
时间: 2024-10-14 03:09:53

HDU 5441 Travel 并查集的相关文章

2015 ACM/ICPC Asia Regional Changchun Online HDU - 5441 (离线+并查集)

题目:http://acm.hdu.edu.cn/showproblem.php?pid=5441 题意:给你n,m,k,代表n个城市,m条边,k次查询,每次查询输入一个x,然后让你一个城市对(u,v)满足两点之间每一条边都不超过x,问有多少对 思路:首先我想到的是dfs求出每个查询小于等于他的一个连通块,然后num*(num-1)就是答案,但是时间只有一秒,这个复杂度是5*1e8,超时了(亲身体验了) 然后我们想这个是离线的,我们可不可以由小到大来推,这样前面的贡献到后面就依然能用了,但是我们

Hdu 2473(并查集删除操作) Junk-Mail Filter

有木有很吊 加强 加强版   啊  ,看了都不敢做了   ,后来先做了食物链这个我还是看过的,但还是A不掉,没明白神魔意思 ,总而言之,大牛的博客是个好东西,我就那么看了一下,还是不懂怎莫办啊,哎,就那样就A掉了....... 今天我们来谈一下这个并查集的删除操作,根据我对大牛的理解啊,这个并查集的删除操作并不是把原来的节点删除掉,而是用一个替身替掉,现在的这个点只是用作桥梁的作用,即是无用的,del  ,,,del  ,,,,删除,那些被删掉的就从n开始给他们一个地址,然后即如下代码所示 #i

HDU 4496 D-City(并查集,逆思维)

题目 熟能生巧...常做这类题,就不会忘记他的思路了... //可以反过来用并查集,还是逐个加边,但是反过来输出...我是白痴.....又没想到 //G++能过,C++却wa,这个也好奇怪呀... #include<stdio.h> #include<string.h> int fx,fy,r,bin[10010]; int x[100010],y[100010],n,m,i,count,ans[100010],j; int find(int x) { //改成这样就不会超时了么好

HDU 1272 简单并查集

小希的迷宫 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 24915    Accepted Submission(s): 7641 Problem Description 上次Gardon的迷宫城堡小希玩了很久(见Problem B),现在她也想设计一个迷宫让Gardon来走.但是她设计迷宫的思路不一样,首先她认为所有的通道都应该是双

hdu 3038 (并查集)

题目大意: 给出m个询问,问[l,r]之间的和   ,求出有多少次询问不和之前的矛盾的. 思路分析: 用并查集记录当前节点到根节点的和. #include <cstdio> #include <iostream> #include <cstring> #include <algorithm> #define maxn 222222 using namespace std; int set[maxn]; int sum[maxn]; int find(int

hdu 5441 Travel 离线带权并查集

Travel Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://acm.hdu.edu.cn/showproblem.php?pid=5441 Description Jack likes to travel around the world, but he doesn’t like to wait. Now, he is traveling in the Undirected Kingdom. There are n cities and m

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 题意:给出一张图,有n个点,m条带权边,每次询问给出一个值val,要求删除权值>val的所有边.然后每次询问求多少个点对相连,ab和ba算成两个点对. 思路: 把每条边的权值按照从小到大排序,把每个询问记录下来,按照从小到大排序. 初始图没有边.然后按照询问加入边.对于每个询问,除了已经加入的边,再加入权值比它小的边. 然后用并查集求得每次加一条边后新产生的点对. 用一个数组cnt[i],来记

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<