[并查集]JZOJ 4223 旅游

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

分析

这道题其实非常简单,把询问混进边里排序就行了,用并查集维护图的连通性,合并的时候加一下答案,用个size数组

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <memory.h>
using namespace std;
const int N=2e4+10;
struct Edge {
    int u,v,w,nx,id,ans;
}g[10*N];
int cnt,list[N];
int sz[N],f[N];
int t,n,m,q;

void Add(int u,int v,int w) {
    g[++cnt]=(Edge){u,v,w,list[u]};list[u]=cnt;
}

int Get_F(int x) {return f[x]==x?x:f[x]=Get_F(f[x]);}

bool CMP(Edge a,Edge b) {return a.w<b.w||a.w==b.w&&a.u>b.u;}

bool CMP_(Edge a,Edge b) {return a.id>b.id;}

int main() {
    for (scanf("%d",&t);t;t--) {
        scanf("%d%d%d",&n,&m,&q);
        cnt=0;memset(list,0,sizeof list);
        for (int i=1,u,v,w;i<=m;i++) scanf("%d%d%d",&u,&v,&w),Add(u,v,w);
        for (int i=1;i<=q;i++) cnt++,scanf("%d",&g[cnt].w),g[cnt].u=g[cnt].v=-1,g[cnt].id=i;
        sort(g+1,g+cnt+1,CMP);
        for (int i=1;i<=n;i++) f[i]=i,sz[i]=1;
        int ans=0;
        for (int i=1;i<=cnt;i++)
            if (g[i].u!=-1) {
                int fu=Get_F(g[i].u),fv=Get_F(g[i].v);
                if (fu==fv) continue;
                ans+=sz[fu]*sz[fv]*2;sz[fu]+=sz[fv];f[fv]=fu;
            }
            else g[i].ans=ans;
        sort(g+1,g+cnt+1,CMP_);
        for (int i=q;i;i--) printf("%d\n",g[i].ans);
    }
}
View Code

猜你喜欢

转载自www.cnblogs.com/mastervan/p/10325906.html