jzoj 4223.【五校联考3day1】旅游 并查集
Description
Input
Output
Sample Input
1
5 5 3
2 3 6334
1 5 15724
3 5 5705
4 3 12382
1 3 21726
6000
10000
13000
Sample Output
2
6
12
Data Constraint
分析:
一开始还以为是克鲁斯卡尔重构树。
发现可以离线其实是一道简单题。
对询问排序,从小到大做。
维护小于等于当前询问值的边的最小生成树即可。
代码:
#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
const int maxn=1e5+7;
using namespace std;
int test,T,n,m,ans;
int p[maxn],size[maxn],f[maxn];
struct rec{
int x,y,w;
}a[maxn];
struct node{
int x,num;
}q[maxn];
bool cmp1(rec a,rec b)
{
return a.w<b.w;
}
bool cmp2(node a,node b)
{
return a.x<b.x;
}
int find(int x)
{
if (!p[x]) return x;
return p[x]=find(p[x]);
}
void uni(int x,int y)
{
int u=find(x),v=find(y);
if (u==v) return;
ans+=size[u]*size[v]*2;
p[u]=v;
size[v]+=size[u];
}
int main()
{
scanf("%d",&test);
while (test--)
{
scanf("%d%d%d",&n,&m,&T);
for (int i=1;i<=m;i++) scanf("%d%d%d",&a[i].x,&a[i].y,&a[i].w);
sort(a+1,a+m+1,cmp1);
for (int i=1;i<=T;i++)
{
scanf("%d",&q[i].x);
q[i].num=i;
}
sort(q+1,q+T+1,cmp2);
ans=0;
for (int i=1;i<=n;i++)
{
p[i]=0;
size[i]=1;
}
int j=1;
for (int i=1;i<=T;i++)
{
while ((j<=m) && (a[j].w<=q[i].x))
{
uni(a[j].x,a[j].y);
j++;
}
f[q[i].num]=ans;
}
for (int i=1;i<=T;i++) printf("%d\n",f[i]);
}
}