hdu5441(2015长春赛区网络赛1005)类最小生成树、并查集

题意:有一张无向图,一些点之间有有权边,某条路径的值等于路径上所有边的边权的最大值,而某个点对的值为这两点间所有路径的值的最小值,给出多个询问,每个询问有一个值,询问有多少点对满足其值小于等于询问值。点的顺序不同算作不同点对。

这题的做法很类似Kruskal算法。一开始所有的点都为一个并查集,从权值最小的边开始,当加入这条边的时候,这条边连接的两个点(并查集)之间相互到达的路径中,值最小的一个路径一定就是通过这条边的,所以这两点间的值就是这条边的权值。之后每加入一条最小边,如果可以用来合并两个并查集,那么这两个并查集中的点相互到达的值一定是这条边的边权,因为我们取出的是边权最小的一条边,之前边权更小的边并没有使这两个并查集连通,而剩余边的话边权又比当前的边的边权大,因此得证,所以符合这个值的答案数就会加上这两个并查集的点数的乘积的两倍。这样这题就能够解决了。首先将边按权值、询问按询问值排序,再通过边合并并查集,合并过程中顺便将符合当前边权的询问赋值,这样就能离线处理出所有询问了。只不过我当时做的时候因为初始化的时候写小了,导致WA了五法……

 1 #include<stdio.h>
 2 #include<string.h>
 3 #include<algorithm>
 4 using namespace std;
 5 const int maxn=20005;
 6 const int maxp=5005;
 7 const int maxm=1e5+5;
 8
 9 struct seg{
10     int a,b,v;
11     bool operator < (const seg a)const{
12         return v<a.v;
13     }
14 }s[maxm];
15
16 struct peo{
17     int num,v,cnt;
18     bool operator < (const peo a)const{
19         return v<a.v;
20     }
21 }p[maxp];
22
23 int n,m;
24 int fa[maxn],num[maxn],ans[maxp];
25 int nnum[100010];
26
27 void init(){
28     for(int i=0;i<=n;i++){fa[i]=i;num[i]=1;}
29     memset(ans,0,sizeof(ans));
30     memset(p,0,sizeof(p));
31 }
32
33 int find(int x){
34     int r=x,t;
35     while(fa[r]!=r)r=fa[r];
36     while(x!=r){
37         t=fa[x];
38         fa[x]=r;
39         x=t;
40     }
41     return r;
42 }
43
44 int main(){
45     int T;
46     scanf("%d",&T);
47     while(T--){
48         int k;
49         scanf("%d%d%d",&n,&m,&k);
50         init();
51         for(int i=1;i<=m;++i)scanf("%d%d%d",&s[i].a,&s[i].b,&s[i].v);
52         int maxx=0;
53         for(int i=1;i<=k;++i){
54             scanf("%d",&p[i].v);
55             p[i].num=i;
56             if(p[i].v>maxx)maxx=p[i].v;
57         }
58         sort(s+1,s+m+1);
59         int pos=1;
60         int aans=0;
61         memset(nnum,0,sizeof(nnum));
62         for(int i=1;i<=m;++i){
63             int x=find(s[i].a),y=find(s[i].b);
64             if(x!=y){
65                 int nx=num[x],ny=num[y];
66                 aans+=nx*ny;
67                 nnum[s[i].v]+=nx*ny*2;
68                 fa[x]=y;
69                 num[y]+=num[x];
70             }
71         }
72         for(int i=1;i<=maxx;++i)nnum[i]+=nnum[i-1];
73         for(int i=1;i<=k;++i)printf("%d\n",nnum[p[i].v]);
74     }
75     return 0;
76 }

时间: 2024-08-06 07:55:56

hdu5441(2015长春赛区网络赛1005)类最小生成树、并查集的相关文章

hdu5443(2015长春赛区网络赛1007)暴力

题意:给了一个数列,有多个询问,每个询问求某个区间内的最大值 数列长度 1000,询问个数 1000,静态,并不需要RMQ这些,直接暴力 n2 查找每个询问区间取最大值就行了. 1 #include<stdio.h> 2 #include<string.h> 3 #include<algorithm> 4 #include<math.h> 5 using namespace std; 6 typedef long long ll; 7 const int m

hdu5442(2015长春赛区网络赛1006)后缀数组+KMP /最小表示法?

题意:给定一个由小写字母组成的长度为 n 的字符串,首尾相连,可以从任意一个字符开始,顺时针或逆时针取这个串(长度为 n),求一个字典序最大的字符串的开始字符位置和顺时针或逆时针.如果有多个字典序最大的字符串,优先选择开始位置靠前的,如果开始位置相同,优先选择顺时针. 这种字符串的问题,第一反应是后缀数组,为了达到首尾相连的目的,所以先复制了一个两倍长的该字符串,然后再将串倒置,也弄成两倍长度,得到顺逆时针的两倍长的串,并对这两个字符串分别做后缀数组,得到 sa 数组(该串字典序第几小的后缀的开

zoj 3659 第37届ACM/ICPC 长春赛区现场赛E题 (并查集)

题意:给出一棵树,找出一个点,求出所有点到这个点的权值和最大,权值为路径上所有边权的最小值. 用神奇的并查集,把路按照权值从大到小排序,然后用类似Kruskal的方法不断的加入边. 对于要加入的一条路,这条路连接这城市x和y,x所在的集合为A, y所在的集合为B, 可以确定A,B集合内的所有路都比当前这条路的权值大.如果让集合B加入集合A,就是让中心城市位于集合A,那么可以确定这两个集合合并之后的总权值为: A的权值总和+B的数量*当前这条路的权值.同样算出让集合B加入集合A的情况,取两者合并后

2015长春赛区区域赛总结

实在不忍心再回顾一番这段惨痛的回忆. 我现在真心觉得,对于ACM,同样是,如果爱,请深爱.只是肤浅的喜欢实在问心有愧.所以,对于最后队伍拿铁,我爆零的这次经历,我真的觉得不堪回首,想过放弃,但是现在偏偏又想死磕,且当做缘分,继续刷刷刷吧. 首先,说热身赛,总共四道题,我们队三个人各自分别敲一道题.然而我们每个人都要敲题,所以我们就要轮流改代码调试,进度相当之慢,而且也确实被codeblocks编译器和ubuntu系统坑爆了.来之前自己熟悉了系统和编译环境,然而并没有完全适应,所以之前遇到的各种问

hdu 4277 2012长春赛区网络赛 dfs+hashmap ***

hashmap判重大法好 1 #include<cstdio> 2 #include<iostream> 3 #include<algorithm> 4 #include<cstring> 5 #include<cmath> 6 #include<queue> 7 #include<map> 8 using namespace std; 9 #define MOD 1000000007 10 const int INF=0

hdu 4272 2012长春赛区网络赛 dfs暴力 ***

总是T,以为要剪枝,后来发现加个map就行了 1 #include<cstdio> 2 #include<iostream> 3 #include<algorithm> 4 #include<cstring> 5 #include<cmath> 6 #include<queue> 7 #include<map> 8 using namespace std; 9 #define MOD 1000000007 10 const

Largest Point (2015沈阳赛区网络赛水题)

Problem Description Given the sequence A with n integers t1,t2,?,tn. Given the integral coefficients a and b. The fact that select two elements ti and tj of A and i≠j to maximize the value of at2i+btj, becomes the largest point. Input An positive int

hdu 4273 2012长春赛区网络赛 三维凸包中心到最近面距离 ***

新模板 1 /* 2 HDU 4273 Rescue 3 给一个三维凸包,求重心到表面的最短距离 4 模板题:三维凸包+多边形重心+点面距离 5 */ 6 7 #include<stdio.h> 8 #include<algorithm> 9 #include<string.h> 10 #include<math.h> 11 #include<stdlib.h> 12 using namespace std; 13 const int MAXN=

hdu 4274 2012长春赛区网络赛 树形dp ***

设定每个节点的上限和下限,之后向上更新,判断是否出现矛盾 1 #include<cstdio> 2 #include<iostream> 3 #include<algorithm> 4 #include<cstring> 5 #include<cmath> 6 #include<queue> 7 #include<map> 8 using namespace std; 9 #define MOD 1000000007 10