题目大意:
q次询问 每次询问x 有多少个点对(a,b)满足这两点间存在一条路径使路径上所有边权<=x
思路:
离线下来并查集
并查集时候记一下连通块大小
1 #include<iostream> 2 #include<cstdio> 3 #include<cmath> 4 #include<cstdlib> 5 #include<cstring> 6 #include<algorithm> 7 #include<vector> 8 #include<queue> 9 #define inf 2139062143 10 #define ll long long 11 #define MAXN 20100 12 using namespace std; 13 inline int read() 14 { 15 int x=0,f=1;char ch=getchar(); 16 while(!isdigit(ch)) {if(ch==‘-‘) f=-1;ch=getchar();} 17 while(isdigit(ch)) {x=x*10+ch-‘0‘;ch=getchar();} 18 return x*f; 19 } 20 int T,n,m,Q,f[MAXN],ans[MAXN],cnt[MAXN],res; 21 int find(int x){return f[x]==x?x:f[x]=find(f[x]);} 22 struct Ask 23 { 24 int val,pos; 25 bool operator < (const Ask &a) const 26 { 27 return val<a.val; 28 } 29 }q[MAXN]; 30 struct Edge 31 { 32 int u,v,val; 33 bool operator < (const Edge &a) const 34 { 35 return val<a.val; 36 } 37 }e[MAXN*5]; 38 int main() 39 { 40 T=read(); 41 while(T--) 42 { 43 n=read(),m=read(),Q=read(),res=0; 44 for(int i=1;i<=n;i++) cnt[i]=1,f[i]=i; 45 for(int i=1;i<=m;i++) e[i].u=read(),e[i].v=read(),e[i].val=read(); 46 for(int i=1;i<=Q;i++) q[i].val=read(),q[i].pos=i; 47 sort(e+1,e+m+1);sort(q+1,q+Q+1);int j=1,a,b; 48 for(int i=1;i<=Q;i++) 49 { 50 while(j<=m&&e[j].val<=q[i].val) 51 { 52 a=find(e[j].u),b=find(e[j].v); 53 if(a!=b) f[b]=a,res+=cnt[a]*cnt[b]*2,cnt[a]+=cnt[b]; 54 j++; 55 } 56 ans[q[i].pos]=res; 57 } 58 for(int i=1;i<=Q;i++) printf("%d\n",ans[i]); 59 } 60 }