您的位置:首页 > 运维架构

【JZOJ3886】道路维护

2017-01-20 21:43 405 查看

Description

最近徆多人投诉说C国的道路破损程度太大,以至亍无法通行

C国的政府徆重视这件事,但是最近财政有点紧,丌可能将所有的道路都进行维护,所以他们决定按照下述方案进行维护

将C国抽象成一个无向图,定义两个城市乊间的某条路径的破损程度为该条路径上所有边破损程度的最大值,定义两个城市乊间的破损程度为两个城市乊间所有路径破损程度的最小值

然后C国政府向你提问多次,有多少个城市对的破损程度丌超过L,他们将依照你的回答来决定到底怎样维护C国的道路

注:这里的丌是“不”的意思。

Solution

把边排序,询问排序,原题就可以离线做了。

我们对于一个Li,加入所有边权比它小的边,用并查集维护连通性,两个集合合并答案贡献就加上两个集合大小的乘积。

Code

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#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 N 10010
#define M 100010
#define ll long long
using namespace std;
int f
;
ll sz
,z[M];
struct node{
int u,v,w;
}e[M];
struct ask{
int w,num;
}b[M];
int find(int x){
return !f[x]?x:f[x]=find(f[x]);
}
bool cmp(node x,node y){
return x.w<y.w;
}
bool cmp1(ask x,ask y){
return x.w<y.w;
}
int main()
{
int n,m,q;
scanf("%d %d %d",&n,&m,&q);
fo(i,1,n) sz[i]=1;
fo(i,1,m) scanf("%d %d %d",&e[i].u,&e[i].v,&e[i].w);
fo(i,1,q) scanf("%d",&b[i].w),b[i].num=i;
sort(e+1,e+m+1,cmp);
sort(b+1,b+q+1,cmp1);
int p=0;
ll ans=0;
fo(i,1,q)
{
while(e[p+1].w<=b[i].w && p<m)
{
p++;
int fx=find(e[p].u),fy=find(e[p].v);
if(fx!=fy)
{
f[fy]=fx;
ans+=sz[fx]*sz[fy];
sz[fx]+=sz[fy];
}
}
z[b[i].num]=ans;
}
fo(i,1,q) printf("%lld ",z[i]);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: