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的主要内容,如果未能解决你的问题,请参考以下文章