hdoj4750 Count The Pairs

来源:互联网 发布:淘宝换货流程明细 编辑:程序博客网 时间:2024/06/06 20:11

把边和询问都按权值排序,然后反过来做,每次找一条最小的边,如果边的两点不在同一个集合,那么他们之间能产生的不能给出的方案数就是集合元素个数之积,然后把这两个集合合并。对于每个询问,把总的方案数减去比它小的不能给出的方案数之和就可以了。



#include<iostream>#include<queue>#include<stdio.h>#include<string>#include<string.h>#include<algorithm>#include<vector>using namespace std;struct node{    int s,t;    long long v;}edge[500010];int n,m,query,father[500010],num[500010];node q[100010];long long ans[100010];bool cmp1(node a,node b){    return a.v<b.v;}int find(int x){    if (father[x]==x) return x;    return father[x]=find(father[x]);}int main(){    int i,j,k;    while (scanf("%d%d",&n,&m)!=EOF)    {        for (i=0;i<n;i++){            father[i]=i;            num[i]=1;        }        for (i=0;i<m;i++){            scanf("%d%d%I64d",&edge[i].s,&edge[i].t,&edge[i].v);        }        scanf("%d",&query);        for (i=0;i<query;i++){            scanf("%I64d",&q[i].v);            q[i].s=i;        }        sort(edge,edge+m,cmp1);        sort(q,q+query,cmp1);        int j=0,tx,ty;        long long tmp=0;        for (i=0;i<query;i++)        {            while (edge[j].v<q[i].v&&j<m)            {                tx=find(edge[j].s);                ty=find(edge[j].t);                if (tx==ty){j++;continue;}                tmp+=num[tx]*num[ty]*2;                num[tx]+=num[ty];                father[ty]=tx;                j++;            }            ans[q[i].s]=n*n-n-tmp;        }        for (i=0;i<query;i++) printf("%I64d\n",ans[i]);    }    return 0;}