HDU3938

Posted whiteli

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HDU3938相关的知识,希望对你有一定的参考价值。

发现可以模拟Kruscal算法,一开始所有点在只包含自己的集合中,然后按照边长从小到大依次合并,每次合并如果发现这条边的两个端点不在同一个集合中,那么答案就加上这两个端点分属的两个集合中的点数相乘。

多次询问,考虑离线处理,答案按l从小到大排序,处理完后再按输入顺序排序输出。

 1 #include<iostream>
 2 #include<string.h>
 3 #include<algorithm>
 4 using namespace std;
 5 int n,m,q,f[10010],s[10010];
 6 struct edge{
 7     int from,to,w;
 8     bool operator < (const edge &a){
 9         return w<a.w;
10     }
11 }e[50010];
12 
13 struct ans{
14     int id,l,cnt;
15 }que[10010];
16 
17 bool cmp1(ans a,ans b){
18     return a.l<b.l;
19 }
20 
21 bool cmp2(ans a,ans b){
22     return a.id<b.id;
23 }
24 
25 void ini(){
26     for (int i=1;i<=n;i++){
27         f[i]=i;
28         s[i]=1;
29     }
30 }
31 
32 int getf(int u){
33     return f[u]==u?f[u]:f[u]=getf(f[u]);
34 }
35 
36 int merge(int u,int v){
37     int uf=getf(u);
38     int vf=getf(v);
39     if (uf==vf) return 0;
40     f[uf]=vf;
41     int tmp=s[vf];
42     s[vf]+=s[uf];
43     return tmp*s[uf];
44 }
45 
46 int main(){
47     while (cin>>n>>m>>q){
48         ini();
49         for (int i=1;i<=m;i++){
50             scanf("%d %d %d",&e[i].from,&e[i].to,&e[i].w);
51         }
52         for (int i=1;i<=q;i++){
53             scanf("%d",&que[i].l);
54             que[i].cnt=0;
55             que[i].id=i;
56         }
57         sort(e+1,e+1+m);
58         sort(que+1,que+1+q,cmp1);
59         int now=1;
60         for (int i=1;i<=q;i++){
61             que[i].cnt=que[i-1].cnt;
62             while (e[now].w<=que[i].l && now<=m){
63                 que[i].cnt+=merge(e[now].from,e[now].to);
64                 now++;
65             }
66         }
67         sort(que+1,que+q+1,cmp2);
68         for (int i=1;i<=q;i++) cout<<que[i].cnt<<endl;
69     }
70     return 0;
71 }

 

以上是关于HDU3938的主要内容,如果未能解决你的问题,请参考以下文章

hdu 3938 portal

hdu 3938 (离线并查集)

HDU 3938 Portal

HDU3938

HDU3938

数值标记问题 离线+树状数组 HDU 3938