【JZOJ3886】道路维护

6 篇文章 0 订阅
2 篇文章 0 订阅

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[N];
ll sz[N],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]);
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值