<>
题目大意:
$n$个点,$m$条边,每条边具有对应的权值,然后进行$k$次询问,每次询问给定一个值,所有权值小于等于这个的边所对应的点能够相连,问每次询问,这些能够相互到达的点所构成的无序点对的个数。解题分析:
数据比较大,每次询问暴力加边肯定超时,所以考虑离线来搞。进行离线查询,将查询按权值从小到大排序,然后每次询问就不需要全部重新添边,只需要增加多余的那一部分即可。#includeusing namespace std;const int N = 1e5+5 , M = 5e3+5;#define REP(i,s,t) for(int i=s;i<=t;i++)struct Edge{ int u,v,val; bool operator < (const Edge&tmp)const{ return val >T; while(T--){ scanf("%d%d%d",&n,&m,&k); REP(i,0,n)fa[i]=i,rk[i]=1; REP(i,1,m)scanf("%d%d%d",&e[i].u,&e[i].v,&e[i].val); sort(e+1,e+1+m); REP(i,1,k)scanf("%d",&q[i].val),q[i].id=i; sort(q+1,q+1+k,cmp); ans=0; int loc=1; REP(i,1,k){ while(loc<=m && e[loc].val<=q[i].val){ Union(e[loc].u,e[loc].v); loc++; } res[q[i].id]=ans; } REP(i,1,k){ printf("%lld\n",res[i]); } }}