hdu5441

来源:互联网 发布:铣床和车床编程区别 编辑:程序博客网 时间:2024/06/05 14:47

题目链接:hdu5441


ps:参考自点击打开链接

题目大意:有一个n个点的无向图,给出m条边的边权,给出q次询问,每次给出一个值,求用到所有边权不大于这个值的边的情况下,能够互相到达的点对的个数(自己到自己不算)。


题目分析:

  • 首先我们对于边按照边权从小到大排序,对于询问按照值从小到大排序。
  • 枚举每次询问,从前到后扫描边,如果下一条边的边权大于当前的询问的值,那么停止,利用并查集记录每个联通块的点的个数。
  • 每次如果某两个联通块合并,那么最终结果就是增加了(son[1]+son[2])×(son[1]+son[2]-1) - son[1] × (son[1]-1) - son[2] ×(son[2]-1)
  • 复杂度O(m) 
代码:
#include <queue>#include <stdio.h>#include <string.h>#include <iostream>#include <algorithm>using namespace std;typedef long long LL;const int maxn=20000+100;const int maxm=100000+100;const int maxq=5000+100;int T,n,m,q;int father[maxn],son[maxn],ans[maxq];struct Edge{    int u,v,w;    bool operator <(const Edge& rhs) const {        return w<rhs.w;    }}edge[maxm];struct Query{    int id,maxedge;    bool operator <(const Query& rhs) const{        return maxedge<rhs.maxedge;    }}query[maxq];void init(){    for(int i=1;i<=n;i++){        son[i]=1;        father[i]=i;    }}int Find(int x){    return father[x]==x?x:(father[x]=Find(father[x]));}void Union(int fa,int fb){    father[fa]=fb;    son[fb]+=son[fa];}int main(){//    freopen("in.txt","r",stdin);//    freopen("out.txt","w",stdout);    ios::sync_with_stdio(false);    for(cin>>T;T--;){        cin>>n>>m>>q;        for(int i=1;i<=m;i++){            cin>>edge[i].u>>edge[i].v>>edge[i].w;        }        sort(edge+1,edge+m+1);        for(int i=1;i<=q;i++){            query[i].id=i;            cin>>query[i].maxedge;        }        sort(query+1,query+q+1);        init();        int j=1,sum=0;        for(int i=1;i<=q;i++){            while(j<=m&&edge[j].w<=query[i].maxedge)            {                int fa=Find(edge[j].u),fb=Find(edge[j].v);                j++;                if(fa==fb)  continue;                sum+=(son[fa]+son[fb])*(son[fa]+son[fb]-1)-son[fa]*(son[fa]-1)-son[fb]*(son[fb]-1);                Union(fa,fb);            }            ans[query[i].id]=sum;        }        for(int i=1;i<=q;i++){            cout<<ans[i]<<endl;        }    }    return 0;}


原创粉丝点击