hdu4750Count The Pairs 并查集

来源:互联网 发布:问答软件名字 编辑:程序博客网 时间:2024/04/20 00:38
//给出n个点,m条边的无向图//对于一个给定的t//找出有多少对(s,t)使得从s到t的所有路线中//这些路线中权值最大得最小值小于等于t即可以//将边以权值从小到大排序//将询问以t从小到大排序//对于每一次加上一条边,如果将两个集合连接//那么可以将上的pair<s,t>为 (ss[fx]*ss[fy])*2个//再要询问值小于这个值的所有询问都加上(ss[fx]*ss[fy])*2//可以用并查集维护集合#include<cstdio>#include<cstring>#include<iostream>#include<algorithm>using namespace std ;const int maxn = 1e4+10 ;const int maxm = 5e5+10 ;const int maxq = 1e5+10 ;struct node{    int u , v , w ;    bool operator < (struct node tmp)const    {        return w < tmp.w ;    }}edge[maxm] ;int F[maxn] ;int ss[maxn] ;int ans[maxq] ;struct Query{    int v ;    int id ;    int sum ;    bool operator < (const struct Query tmp)const    {        return v < tmp.v ;    }}q[maxq] ;int find(int x){    if(F[x] == -1)    return x ;    return F[x] = find(F[x]) ;}int join(int x , int y){    int fx = find(x) ;    int fy = find(y) ;    if(fx == fy)return 0 ;    int sum = (ss[fx]*ss[fy])*2 ;    F[fx] = fy ;    ss[fy] += ss[fx] ;    return sum ;}int find_pos(int l , int r , int v){    while(l<=r)    {        int mid = (l + r) >> 1 ;        if(q[mid].v <= v)        l = mid + 1 ;        else r = mid - 1;    }    return r ;}int main(){    //freopen("in.txt" , "r" , stdin) ;    int n , m ;    while(~scanf("%d%d" , &n , &m))    {        memset(F , -1 , sizeof(F)) ;        for(int i = 0;i <= n;i++)        ss[i] = 1 ;        for(int i = 1;i <= m;i++)        scanf("%d%d%d" , &edge[i].u , &edge[i].v , &edge[i].w) ;        sort(edge+1 , edge+1+m) ;        int Q ;        scanf("%d" , &Q) ;        for(int i = 1;i <= Q;i++)        scanf("%d" , &q[i].v) , q[i].id = i ,q[i].sum = 0 ;        sort(q + 1 ,q + 1+ Q) ;        for(int i = 1;i <= m;i++)        {            int pos = find_pos(1 , Q , edge[i].w) ;            int sum = join(edge[i].u , edge[i].v );            q[1].sum += sum ;            q[pos+1].sum -= sum ;        }        for(int i = 1;i <= Q;i++)        q[i].sum += q[i-1].sum , ans[q[i].id] = q[i].sum ;        for(int i = 1;i <= Q;i++)        printf("%d\n", ans[i]) ;    }    return 0 ;}
0 0