hdu4750(离线并查集+思路)

题意:

n个点,m条边的无向图,每条边a b c,点a到点b的权值是c。
p(0<p<=100000)个人,以下p行每行有一个值t,找出有多少对点(i, j)满足f大于等于t。
f值的定义:从i点到j点,有好几种走法,每种走法中取路径中权值最大的边值,所有走法中的值中,取最小的那个即为f值

//#pragma comment(linker, "/STACK:102400000")
#include<cstdlib>
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<set>
#include<map>
#include<list>
#include<queue>
#include<vector>
#define tree int o,int l,int r
#define lson o<<1,l,mid
#define rson o<<1|1,mid+1,r
#define lo o<<1
#define ro o<<1|1
#define ULL unsigned long long
#define LL long long
#define inf 0x7fffffff
#define eps 1e-7
#define N 10005
#define M 500009
using namespace std;
int m,n,T,t,x,y,u,qn;
struct Node
{
    int x,y,val;
    bool operator<(const Node a)const
    {
        return val<a.val;
    }
} node[M];
int q[M/5+100],f[M/5+100],ans[M/5+100];
int s[N],cnt[N];
bool cmp(int a,int b)
{
    return q[a]<q[b];
}
int find(int x)
{
    return x==s[x]?x:s[x]=find(s[x]);
}
int main()
{
#ifndef ONLINE_JUDGE
    freopen("ex.in","r",stdin);
#endif
//    scanf("%d",&T);
//    while(T--)
    int ncase=0;
    while(scanf("%d%d",&n,&m)==2)
    {
        for(int i=0; i<m; ++i)
            scanf("%d%d%d",&node[i].x,&node[i].y,&node[i].val);
        sort(node,node+m);
        scanf("%d",&qn);
        for(int i=0; i<qn; i++)
        {
            scanf("%d",&q[i]);
            f[i]=i;
        }
        sort(f,f+qn,cmp);
        for(int i=0; i<=n; i++)
        {
            s[i]=i;
            cnt[i]=1;
        }
        int tp=0,j=0;
        for(int i=0; i<qn; i++)
        {
            int sub=f[i];
            while(j<m&&node[j].val<q[sub])
            {

                int u=node[j].x,v=node[j].y;
                int toux=find(u);
                int touy=find(v);
                if(toux!=touy)
                {
                    tp+=cnt[touy]*cnt[toux];
                    s[touy]=toux;
                    cnt[toux]+=cnt[touy];
                }
                j++;
            }
            ans[sub]=tp;
        }
        while(j<m)//WA,求tp
        {
            int u=node[j].x,v=node[j].y;
            int toux=find(u);
            int touy=find(v);
            if(toux!=touy)
            {
                tp+=cnt[touy]*cnt[toux];
                s[touy]=toux;
                cnt[toux]+=cnt[touy];
            }
            j++;
        }
        for(int i=0; i<qn; i++)
            printf("%d
",(tp-ans[i])*2);
    }
    return 0;
}
原文地址:https://www.cnblogs.com/sbaof/p/3332800.html