题目大意
在Byteland一共有n 个城市,编号依次为1 到n,它们之间计划修建m条双向道路,其中修建第i 条道路的费用为ci。
Byteasar作为Byteland 公路建设项目的总工程师,他决定选定一个区间[l, r],仅使用编号在该区间内的道路。他希望选择一些道路去修建,使得连通块的个数尽量少,同时,他不喜欢修建多余的道路,因此每个连通块都可以看成一棵树的结构。
为了选出最佳的区间,Byteasar 会不断选择q 个区间,请写一个程序,帮助Byteasar 计算每个区间内修建公路的最小总费用。
解题思路
用线段树维护每个区间边的mst,归并合并,查询同理。
code
#include
#include
#include
#include
#include
#define LD double
#define LL long long
#define ULL unsigned long long
#define min(a,b) ((a
#define max(a,b) ((a>b)?a:b)
#define fo(i,j,k) for(int i=j;i<=k;i++)
#define fd(i,j,k) for(int i=j;i>=k;i--)
#define fr(i,j) for(int i=begin[j];i;i=next[i])
using namespace std;
int const mn=100+9,mm=1e5+9,inf=1e9;
int n,m,q,cnt,fa[mn];
struct rec{
int u,v,c;
};
rec a[mm];
struct rec2{
int size,ans;
rec a[101];
};
rec2 b[mm*4],d[3];
int get(int x){
if(!fa[x])return x;
return fa[x]=get(fa[x]);
}
void merge(rec2 &x,rec2 &y,rec2 &z){
int i=1,j=1,k=0;d[0].ans=0;
while((i<=x.size)||(j<=y.size)){
if((j>y.size)||((i<=x.size)&&(x.a[i].cint fu=get(x.a[i].u),fv=get(x.a[i].v);
if(fu!=fv){
fa[fu]=fv;d[0].ans+=x.a[i].c;
d[0].a[++k]=x.a[i];
}
i++;
}else{
int fu=get(y.a[j].u),fv=get(y.a[j].v);
if(fu!=fv){
fa[fu]=fv;d[0].ans+=y.a[j].c;
d[0].a[++k]=y.a[j];
}
j++;
}
}
d[0].size=k;
z.ans=d[0].ans;z.size=d[0].size;
fo(i,1,k)fa[d[0].a[i].u]=fa[d[0].a[i].v]=0,z.a[i]=d[0].a[i];
}
void build(int now,int l,int r){
if(l==r){
b[now].a[1]=a[l];
b[now].size=1;
b[now].ans=a[l].c;
return;
}
int mid=(l+r)>>1,lson=now*2,rson=now*2+1;
build(lson,l,mid);
build(rson,mid+1,r);
merge(b[lson],b[rson],b[now]);
}
void qury(int now,int l,int r,int u,int v){
int mid=(l+r)>>1;
if((l==u)&&(r==v)){
d[++cnt].size=b[now].size;d[cnt].ans=b[now].ans;
fo(i,1,d[cnt].size)d[cnt].a[i]=b[now].a[i];
if(cnt==2){
merge(d[1],d[2],d[1]);
cnt=1;
}
return;
}
if(v<=mid)qury(now*2,l,mid,u,v);
else if(mid2+1,mid+1,r,u,v);
else{
qury(now*2,l,mid,u,mid);
qury(now*2+1,mid+1,r,mid+1,v);
}
}
int main(){
freopen("d.in","r",stdin);
freopen("d.out","w",stdout);
scanf("%d%d%d",&n,&m,&q);
fo(i,1,m)scanf("%d%d%d",&a[i].u,&a[i].v,&a[i].c);
build(1,1,m);int l,r;
fo(cas,1,q){
scanf("%d%d",&l,&r);
if(cas==469){
int bb;
bb++;
}
qury(1,1,m,l,r);
printf("%d\n",d[1].ans);cnt=0;
}
return 0;
}