Count The Pairs HDU - 4750

点击打开链接

以前的一道题目 想起来又做了一遍 当时真的是毫无头绪 看了博客还是半懂不懂

现在独立思考已经可以有比较清晰地思路 也可能是因为做过类似的题目吧

题目所说的两点间f值即是 两点间所有路径中最长边的最小值 用最小生成树解决

先将边升序排序 这样当前遍历到的每一条边都是最长的 这个性质非常好

假设当前遍历到的边的两个点之前是不连通的 这样在两点间路径中的最长边(f值)就确定是当前边了

如果此两点之前已经连通 即是说两点间路径中最长边已经有了 但由于当前遍历到的边是最长的 所以不会再更新此两点的f值 可以忽略 符合最小生成树的操作

#include <bits/stdc++.h>
using namespace std;

struct node
{
    int u;
    int v;
    int w;
};

node edge[500010];
int f[10010],num[10010],len[10010],pre[10010],presum[10010];
int n,m;

int cmp(node n1,node n2)
{
    return n1.w<n2.w;
}

int getf(int p)
{
    if(f[p]==p) return p;
    else
    {
        f[p]=getf(f[p]);
        return f[p];
    }
}

int unite(int u,int v)
{
    int fu,fv,sum;
    fu=getf(u);
    fv=getf(v);
    if(fu!=fv)
    {
        f[fv]=fu;
        sum=num[fu]*num[fv];
        num[fu]+=num[fv];
        num[fv]=0;
        return sum;
    }
    else
    {
        return 0;
    }
}

int main()
{
    int i,j,cnt,u,v,w,t,q,p;
    while(scanf("%d%d",&n,&m)!=EOF)
    {
        for(i=1;i<=m;i++)
        {
            scanf("%d%d%d",&edge[i].u,&edge[i].v,&edge[i].w);
        }
        sort(edge+1,edge+m+1,cmp);
        for(i=0;i<n;i++)
        {
            f[i]=i;
            num[i]=1;
        }
        memset(pre,0,sizeof(pre));
        cnt=0;
        for(i=1;i<=m;i++)
        {
            t=unite(edge[i].u,edge[i].v);
            if(t!=0)
            {
                cnt++;
                len[cnt]=edge[i].w;
                pre[cnt]=t;
            }
            if(cnt==n-1) break;
        }
        memset(presum,0,sizeof(presum));
        for(i=cnt;i>=1;i--)
        {
            presum[i]=presum[i+1]+pre[i];
        }
        scanf("%d",&q);
        while(q--)
        {
            scanf("%d",&p);
            p=lower_bound(len+1,len+cnt+1,p)-len;
            printf("%d\n",presum[p]*2);
        }
    }
    return 0;
}

 

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值