【题目】
BZOJ
n
n
n个点
m
m
m条边的无向图,
Q
Q
Q次询问只用编号在
[
l
,
r
]
[l,r]
[l,r]中的边形成的最小生成树(森林)花费。
n
≤
100
,
m
≤
1
0
5
,
Q
≤
15000
n\leq 100,m\leq 10^5,Q\leq 15000
n≤100,m≤105,Q≤15000
【解题思路】
每个区间有用的边数至多
n
n
n条,由于
n
n
n很小,我们可以用线段树维护区间有用的边,区间合并时暴力归并即可,每次合并的复杂度是
O
(
n
log
n
)
O(n\log n)
O(nlogn)的。
复杂度
O
(
(
m
+
Q
)
n
log
n
)
O((m+Q)n\log n)
O((m+Q)nlogn)
【参考代码】
#include<bits/stdc++.h>
#define pb push_back
using namespace std;
const int N=105,M=4e5+10;
typedef vector<int> vi;
int n,m,Q;
namespace IO
{
int read()
{
int ret=0;char c=getchar();
while(!isdigit(c)) c=getchar();
while(isdigit(c)) ret=ret*10+(c^48),c=getchar();
return ret;
}
void write(int x){if(x>9)write(x/10);putchar(x%10^48);}
void writeln(int x){write(x);putchar('\n');}
}
using namespace IO;
namespace WAYS
{
int fa[N];vi tmp;
struct edge
{
int u,v,w;
void in(){u=read();v=read();w=read();}
}e[M];
void dsureset(){for(int i=1;i<=n;++i)fa[i]=i;tmp.clear();}
int findf(int x){return fa[x]==x?x:fa[x]=findf(fa[x]);}
void insert(const int&a)
{
int x=findf(e[a].u),y=findf(e[a].v);
if(x==y) return;
fa[x]=y;tmp.pb(a);
}
int getcost(const vi&a)
{
int res=0;
for(int i=0;i<(int)a.size();++i) res+=e[a[i]].w;
return res;
}
}
using namespace WAYS;
namespace Segment
{
#define ls (x<<1)
#define rs (x<<1|1)
struct Segmemt
{
vi vec[M];
vi merge(const vi&a,const vi&b)
{
int la=a.size(),lb=b.size(),i,j;dsureset();
for(i=0,j=0;i<la && j<lb;)
{
if(e[a[i]].w<e[b[j]].w) insert(a[i]),++i;
else insert(b[j]),++j;
}
for(;i<la;++i) insert(a[i]);
for(;j<lb;++j) insert(b[j]);
return tmp;
}
void build(int x,int l,int r)
{
if(l==r){vec[x].pb(l);return;}
int mid=(l+r)>>1;
build(ls,l,mid);build(rs,mid+1,r);
vec[x]=merge(vec[ls],vec[rs]);
}
vi query(int x,int l,int r,int L,int R)
{
if(L<=l && r<=R) return vec[x];
int mid=(l+r)>>1;vi res;res.clear();
if(L<=mid) res=query(ls,l,mid,L,R);
if(R>mid) res=merge(res,query(rs,mid+1,r,L,R));
return res;
}
}tr;
#undef ls
#undef rs
}
using namespace Segment;
namespace DreamLolita
{
void solution()
{
n=read();m=read();Q=read();
for(int i=1;i<=m;++i) e[i].in();
tr.build(1,1,m);
while(Q--)
{
int l=read(),r=read();
writeln(getcost(tr.query(1,1,m,l,r)));
}
}
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("BZOJ5216.in","r",stdin);
freopen("BZOJ5216.out","w",stdout);
#endif
DreamLolita::solution();
return 0;
}