jzoj3886. 【长郡NOIP2014模拟10.22】道路维护

Description

最近徆多人投诉说C国的道路破损程度太大,以至亍无法通行
C国的政府徆重视这件事,但是最近财政有点紧,丌可能将所有的道路都进行维护,所以他们决定按照下述方案进行维护
将C国抽象成一个无向图,定义两个城市乊间的某条路径的破损程度为该条路径上所有边破损程度的最大值,定义两个城市乊间的破损程度为两个城市乊间所有路径破损程度的最小值
然后C国政府向你提问多次,有多少个城市对的破损程度丌超过L,他们将依照你的回答来决定到底怎样维护C国的道路

分析

昨天刚讲了并查集,今天就有一道并查集的大水题。
我们可以离线做,排序边和询问。
从小到大加边,维护并查集的大小,更新答案。

#include<algorithm>
#include<cstdio>
using namespace std;
struct dd
{
    int x,y,z;
}a[100005];
struct ddd
{
    int l,wz;
}b[100005];
int n,m,q,j,k,f1,f2,t,l[100005],fa[10005],size[100005],ans[100005];
bool cmp(dd a,dd b)
{
    return a.z<b.z;
}
bool cmp1(ddd a,ddd b)
{
    return a.l<b.l;
}
int get(int x)
{
    if (fa[x]==x) return x;
    return fa[x]=get(fa[x]);
}
int g(int x)
{
    return x*(x-1)/2;
}
int main()
{
    scanf("%d%d%d",&n,&m,&q);
    for (int i=1;i<=m;i++) scanf("%d%d%d",&a[i].x,&a[i].y,&a[i].z);
    sort(a+1,a+m+1,cmp);
    for (int i=1;i<=q;i++) scanf("%d",&b[i],l),b[i].wz=i;
    sort(b+1,b+q+1,cmp1);
    for (int i=1;i<=n;i++) fa[i]=i,size[i]=1;
    j=1;
    t=0;
    for (int i=1;i<=q;i++)
    {
        while (a[j].z<=b[i].l && j<=m)
        {
            f1=get(a[j].x),f2=get(a[j].y);
            if (f1!=f2)
            {
                t-=g(size[f2])+g(size[f1]);
                size[f2]+=size[f1];
                size[f1]=0;
                t+=g(size[f2]);
                fa[f1]=f2;
            }
            j++;
        }
        ans[b[i].wz]=t;
    }
    for (int i=1;i<=q;i++) printf("%d ",ans[i]);
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值