版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_34454069/article/details/88015410
分析:
用线段树维护某个区间内的最优边(最多N条)
所以复杂度就是
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<vector>
#define SF scanf
#define PF printf
#define MAXN 110
#define MAXM 100010
using namespace std;
struct node{
int val,u,v;
bool operator <(const node &a) const {
return val<a.val;
}
}e[MAXM];
int tmp[MAXN*2],sum[MAXN],tree[MAXM*4][MAXN];
int fa[MAXN];
int get_fa(int x){
if(fa[x]==0)
return x;
fa[x]=get_fa(fa[x]);
return fa[x];
}
bool merge(int u,int v){
u=get_fa(u);
v=get_fa(v);
if(u==v)
return 0;
fa[u]=v;
return 1;
}
bool sort_by_val(int a,int b){
return e[a]<e[b];
}
void merge(int *res,int* a,int* b){
tmp[0]=0;
memset(fa,0,sizeof fa);
for(int i=1,j=1;i<=a[0]||j<=b[0];){
if(i<=a[0]&&(j>b[0]||e[a[i]]<e[b[j]])){
tmp[++tmp[0]]=a[i];
i++;
}
else{
tmp[++tmp[0]]=b[j];
j++;
}
}
res[0]=0;
for(int i=1;i<=tmp[0];i++)
if(merge(e[tmp[i]].u,e[tmp[i]].v))
res[++res[0]]=tmp[i];
}
void build(int l,int r,int id){
if(l==r){
tree[id][0]=1;
tree[id][1]=l;
return ;
}
int mid=(l+r)>>1;
build(l,mid,id<<1);
build(mid+1,r,id<<1|1);
merge(tree[id],tree[id<<1],tree[id<<1|1]);
}
void query(int l,int r,int id,int l1,int r1){
if(l>=l1&&r<=r1){
merge(sum,sum,tree[id]);
return ;
}
int mid=(l+r)>>1;
if(l1<=mid)
query(l,mid,id<<1,l1,r1);
if(r1>mid)
query(mid+1,r,id<<1|1,l1,r1);
}
int main(){
int n,m,q,l,r;
SF("%d%d%d",&n,&m,&q);
for(int i=1;i<=m;i++)
SF("%d%d%d",&e[i].u,&e[i].v,&e[i].val);
build(1,m,1);
for(int i=1;i<=q;i++){
SF("%d%d",&l,&r);
sum[0]=0;
query(1,m,1,l,r);
int ans=0;
for(int i=1;i<=sum[0];i++)
ans+=e[sum[i]].val;
PF("%d\n",ans);
}
}