现在的位置: 首页 > 综合 > 正文

HDOJ 4750 – Count The Pairs 并查集

2013年10月31日 ⁄ 综合 ⁄ 共 1395字 ⁄ 字号 评论关闭

               题意:

                        定义f(u,v)为u到v每条路径上的最大边的最小值..现在有一些询问..问f(u,v)>=t的点对有所少对..注意(1,2)和(2,1)是不同的点对...

               题解:

                        正过来想不太好做..反过来..看在当前t的限制下..有多少个点对f(u,v)<t...这样答案就是totol-num...totol是总对数n*(n-1)...num是当前可联通的..

                        这样转化后就不难想到将所有的询问从小到大排序..将所有的边从小到大排序..然后根据递增的询问不断地加边统计答案..而要统计答案和维护图的联通关系时用到并查集....如此时间复杂度为O(m)..

Program:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<queue>
#include<vector>
#include<cstdlib>
#include<stack>
#include<map>
#define MAXN 10005
#define MAXM 1000505
#define ll long long 
#define eps 1e-10
using namespace std; 
struct node
{
    int x,y,d,next;
}edge[MAXM];
struct NODE1
{
    int x,y,d;
}E[MAXM];
struct NODE2
{
    ll w,id;
}q[MAXM]; 
int father[MAXN];
ll ans[MAXM],num[MAXN];
bool cmp1(NODE1 a,NODE1 b)
{
    return a.d<b.d;
}
bool cmp2(NODE2 a,NODE2 b)
{
    return a.w<b.w;
}
int getfather(int x)
{
    if (father[x]==x) return x;
    return father[x]=getfather(father[x]);
}
int main()
{
    int n,m,x,y,d,p,i,t;
    ll totol,A; 
    while(~scanf("%d%d",&n,&m))
    { 
           for (i=1;i<=m;i++) scanf("%d%d%d",&E[i].x,&E[i].y,&E[i].d); 
           scanf("%d",&p),totol=n*(n-1);
           for (i=1;i<=p;i++) scanf("%I64d",&q[i].w),q[i].id=i;
           sort(E+1,E+1+m,cmp1),sort(q+1,q+1+p,cmp2);
           for (i=0;i<n;i++) father[i]=i,num[i]=1;
           A=0,t=1;
           for (i=1;i<=p;i++) 
           {
                   d=q[i].w;
                   while (t<=m && E[t].d<d)
                   {
                           x=getfather(E[t].x),y=getfather(E[t].y);
                           if (x==y) { t++; continue; }
                           A+=num[x]*num[y]*2;
                           num[y]+=num[x];
                           father[x]=y;                
                           t++;        
                   }
                   ans[q[i].id]=totol-A;
           }
           for (i=1;i<=p;i++) printf("%I64d\n",ans[i]);
    }
    return 0;
}

抱歉!评论已关闭.