zoukankan      html  css  js  c++  java
  • bzoj 5216: [Lydsy2017省队十连测]公路建设

    5216: [Lydsy2017省队十连测]公路建设

    Time Limit: 20 Sec  Memory Limit: 512 MB
    Submit: 66  Solved: 37
    [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<=15000
     

    Output

    输出q 行,每行一个整数,即最小总费用。
     

    Sample Input

    3 5 2
    1 3 2
    2 3 1
    2 1 6
    3 1 7
    2 3 7
    2 5
    3 4

    Sample Output

    7
    13

    HINT

     

    Source

    Claris原创,本站版权所有

        对边建线段树,对于线段树上一个节点对应的区间,我们记录下这个区间的边在原图中形成的最小生成森林的边是哪些。因为n<=100,所以最小生成森林最多只有99条边。然后我们合并的时候暴力一点,直接做一遍kruscal类似的东西,一次的复杂度是 O(N)。

        因为合并的时候可以直接归并,所以不用对边的权值排序,最后答案就是最小生成森林的边权和(这不是废话么2333)

    #include<bits/stdc++.h>
    #define ll long long
    using namespace std;
    const int maxn=100005;
    struct lines{
    	int u,v,w;
    }l[maxn];
    int p[105],ans,n,m,Q,le,ri;
    int ff(int x){ return p[x]==x?x:(p[x]=ff(p[x]));}
    inline bool can(int x){
    	int X=ff(l[x].u),Y=ff(l[x].v);
    	if(X!=Y){
    		p[X]=Y;
    		return 1;
    	}
    	else return 0;
    }
    struct node{
    	int L[105],num;
    	node operator +(const node &x)const{
    		node r;
    		r.num=0;
    		for(int i=1;i<=n;i++) p[i]=i;
    		int j=1;
    		for(int i=1;i<=num;i++){
    			for(;j<=x.num&&l[x.L[j]].w<l[L[i]].w;j++)
    				if(can(x.L[j])) r.L[++r.num]=x.L[j];
    			if(can(L[i])) r.L[++r.num]=L[i];
    		}
    		for(;j<=x.num;j++) if(can(x.L[j])) r.L[++r.num]=x.L[j];
    		
    		return r;
    	}
    }a[maxn<<2|1],ANS;
    
    void build(int o,int l,int r){
    	if(l==r){
    		a[o].L[a[o].num=1]=l;
    		return;
    	}
    	int mid=l+r>>1,lc=o<<1,rc=(o<<1)|1;
    	build(lc,l,mid),build(rc,mid+1,r);
    	a[o]=a[lc]+a[rc];
    }
    
    void query(int o,int l,int r){
    	if(l>=le&&r<=ri){
    	    ANS=ANS+a[o];
    	    return;
    	}
    	int mid=l+r>>1,lc=o<<1,rc=(o<<1)|1;
    	if(le<=mid) query(lc,l,mid);
    	if(ri>mid) query(rc,mid+1,r);
    }
    
    inline void prework(){
    	for(int i=1;i<=m;i++) scanf("%d%d%d",&l[i].u,&l[i].v,&l[i].w);
    	build(1,1,m);
    }
    
    inline void solve(){
    	while(Q--){
    		scanf("%d%d",&le,&ri);
    		ANS.num=0;
    		query(1,1,m),ans=0;
    		for(int i=1;i<=ANS.num;i++) ans+=l[ANS.L[i]].w;
    		printf("%d
    ",ans);
    	}
    }
    
    int main(){
    	scanf("%d%d%d",&n,&m,&Q);
    	prework();
    	solve();
    	return 0;
    }
    

      

  • 相关阅读:
    Redis的特点什么是?
    Linux---用户和用户管理--用户配置文件
    python---模仿键盘
    Linux---脚本安装包
    python---创建句柄
    python---模仿鼠标悬停 move_to_element/perform/context_click
    python---总结所学元素及方法
    python---关闭 close,quit
    python---截屏
    python---前进和后退 back/forward
  • 原文地址:https://www.cnblogs.com/JYYHH/p/8762454.html
Copyright © 2011-2022 走看看