[HDU 5441]Travel:并查集

来源:互联网 发布:实体类转json 编辑:程序博客网 时间:2024/06/02 12:51

点击这里查看原题

离线处理,将所有边和询问读入后按x排序,从小到大加边,若不在同一个联通块内则ans加上两个联通块合并后的答案,减去原来的两个块的答案。

/*User:SmallLanguage:C++Problem No.:5441*/#include<bits/stdc++.h>#define ll long long#define inf 999999999using namespace std;int ans[5005],pre[20005],num[20005],n,m,k;struct no{    int x,id;}p[5005];struct edge{    int u,v,w;}e[100005];void init(){    for(int i=1;i<=n;i++){        pre[i]=i;        num[i]=1;    }}bool cmpw(edge a,edge b){    return a.w<b.w;}bool cmpx(no a,no b){    return a.x<b.x;}int get(int x){    return x==pre[x]?x:pre[x]=get(pre[x]);}void cal(){    int res=0;    for(int i=1,j=1;i<=k;i++){        while(j<=m&&e[j].w<=p[i].x){            int u=get(e[j].u),v=get(e[j].v);            if(u!=v){                res+=(num[u]+num[v])*(num[u]+num[v]-1)-num[u]*(num[u]-1)-num[v]*(num[v]-1);                pre[v]=u;                num[u]+=num[v];            }            j++;        }        ans[p[i].id]=res;    }}void solve(){    cin>>n>>m>>k;    for(int i=1;i<=n;i++){        pre[i]=i;        num[i]=1;    }    for(int i=1;i<=m;i++)        cin>>e[i].u>>e[i].v>>e[i].w;    for(int i=1;i<=k;i++){        cin>>p[i].x;        p[i].id=i;    }    sort(e+1,e+m+1,cmpw);    sort(p+1,p+k+1,cmpx);    cal();    for(int i=1;i<=k;i++)        cout<<ans[i]<<endl;}int main(){    freopen("data.in","r",stdin);//    ios::sync_with_stdio(false);    int t;    cin>>t;    while(t--) solve();    return 0;}
0 0
原创粉丝点击