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;
}