bzoj 5216 [Lydsy2017省队十连测]公路建设 线段树维护 最小生成树
生活随笔
收集整理的這篇文章主要介紹了
bzoj 5216 [Lydsy2017省队十连测]公路建设 线段树维护 最小生成树
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
?[Lydsy2017省隊十連測]公路建設
Time Limit:?20 Sec??Memory Limit:?512 MBSubmit:?93??Solved:?53
[Submit][Status][Discuss]
Description
在Byteland一共有n個城市,編號依次為1到n,它們之間計劃修建m條雙向道路,其中修建第i條道路的費用為ci。B yteasar作為Byteland公路建設項目的總工程師,他決定選定一個區間[l,r],僅使用編號在該區間內的道路。他希 望選擇一些道路去修建,使得連通塊的個數盡量少,同時,他不喜歡修建多余的道路,因此每個連通塊都可以看成 一棵樹的結構。為了選出最佳的區間, Byteasar會不斷選擇 q個區間,請寫一個程序,幫助 Byteasar計算每個區 間內修建公路的最小總費用。?Input
第一行包含三個正整數n; m; q,表示城市數、道路數和詢問數。 接下來m 行,每行三個正整數ui; vi; ci,表示一條連接城市ui 和vi 的雙向道路,費用為ci。 接下來q 行,每行兩個正整數li; ri,表示一個詢問。 1 ≤ ui, vi ≤ n, ui ?= vi, 1 ≤ li ≤ ri ≤ m, 1 ≤ ci ≤ 10^6 N<=100,M<=100000,Q<=15000Output
輸出q 行,每行一個整數,即最小總費用。Sample Input
3 5 21 3 2
2 3 1
2 1 6
3 1 7
2 3 7
2 5
3 4
Sample Output
713
HINT
題解:因為點數極少所以有用的邊只有n-1條,因為最小生成樹, 所以線段樹每個節點維護的邊只需要有用的那幾條就可以了。 1 #include<cstring> 2 #include<cstdio> 3 #include<algorithm> 4 #include<iostream> 5 #include<cmath> 6 7 #define N 107 8 #define M 100007 9 #define ls p<<1 10 #define rs p<<1|1 11 using namespace std; 12 inline int read() 13 { 14 int x=0,f=1;char ch=getchar(); 15 while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();} 16 while(isdigit(ch)){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();} 17 return x*f; 18 } 19 20 int n,m,q; 21 int fz[M],fa[N]; 22 struct Data 23 { 24 int x,y,z; 25 }a[M]; 26 struct Node 27 { 28 int sum,a[N]; 29 void init() 30 { 31 sum=0; 32 memset(a,0,sizeof(a)); 33 } 34 }tr[M<<2],ans; 35 36 int find(int x) 37 { 38 if (fa[x]!=x) fa[x]=find(fa[x]); 39 return fa[x]; 40 } 41 Node merge(Node y,Node z) 42 { 43 Node x;x.init(); 44 int i=1,j=1,k=0,op=0; 45 while(a[y.a[i]].z&&a[z.a[j]].z) 46 if (a[y.a[i]].z<a[z.a[j]].z) fz[++k]=y.a[i++]; 47 else fz[++k]=z.a[j++]; 48 while(a[y.a[i]].z) fz[++k]=y.a[i++]; 49 while(a[z.a[j]].z) fz[++k]=z.a[j++]; 50 for (int i=1;i<=n;i++) fa[i]=i; 51 for (int i=1;i<=k;i++) 52 { 53 int u=find(a[fz[i]].x),v=find(a[fz[i]].y); 54 if (u!=v) 55 { 56 fa[u]=v; 57 x.sum+=a[fz[i]].z,x.a[++op]=fz[i]; 58 } 59 } 60 return x; 61 } 62 void build(int p,int l,int r) 63 { 64 if (l==r) 65 { 66 tr[p].sum=a[l].z; 67 tr[p].a[1]=l; 68 return; 69 } 70 int mid=(l+r)>>1; 71 build(ls,l,mid),build(rs,mid+1,r); 72 tr[p]=merge(tr[ls],tr[rs]); 73 } 74 Node tree_find(int p,int l,int r,int x,int y) 75 { 76 if (l==x&&r==y) return tr[p]; 77 int mid=(l+r)>>1; 78 if (y<=mid) return tree_find(ls,l,mid,x,y); 79 else if (x>mid) return tree_find(rs,mid+1,r,x,y); 80 else return merge(tree_find(ls,l,mid,x,mid),tree_find(rs,mid+1,r,mid+1,y)); 81 } 82 int main() 83 { 84 n=read(),m=read(),q=read(); 85 for (int i=1;i<=m;i++) 86 a[i].x=read(),a[i].y=read(),a[i].z=read(); 87 build(1,1,m); 88 while(q--) 89 { 90 int l=read(),r=read(); 91 ans=tree_find(1,1,m,l,r); 92 printf("%d\n",ans.sum); 93 } 94 }?
轉載于:https://www.cnblogs.com/fengzhiyuan/p/8848369.html
總結
以上是生活随笔為你收集整理的bzoj 5216 [Lydsy2017省队十连测]公路建设 线段树维护 最小生成树的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 虚拟机CentOS7开机报错:you m
- 下一篇: Python fire官方文档教学(自动