图论专题--P2504 [HAOI2006]聪明的猴子

12 篇文章 0 订阅

 最小生成树的一个重要性质:最小生成树的最大边权是所有生成树的最大边权中最小的

所有只要做一个最小生成树,途中记录最大边权就可以了

我用的是kruskal来做生成树,最后把存猴子步长的数组遍历一遍看有多少能跳过最长的边就行了

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

int p[1005],leap[505],x[1005],y[1005];
int M,N,num=0;
double MAX=-1;      //用来存储最小生成树的最大边

struct Edge
{
    int a,b;   
    double w;
}edge[5000000];

bool cmp(Edge A,Edge B)  //一个按边长从小到大的排序方法
{
    return A.w<B.w;
}    

int find(int x)     //并查集标准find函数
{
    if(p[x] != x) return find(p[x]);
    else return p[x];
}

int main()
{
    scanf("%d",&M);
    for(int i = 1; i <= M; i ++) scanf("%d",&leap[i]);
    scanf("%d",&N);
    for(int i = 1; i <= N; i ++) scanf("%d%d",&x[i],&y[i]);
    
    //输入结束,该算边长了
    int cnt = 0;
    for(int i = 1; i <= N; i ++)
    {
        for(int j = 1; j <= N; j ++)
        {
            if(i != j)
            {
                edge[++cnt].a = i;
                edge[cnt].b = j;
                edge[cnt].w = sqrt((x[i] - x[j]) * (x[i] - x[j]) + (y[i] - y[j]) * (y[i] - y[j]));
            }
        }
    }
    
    sort(edge + 1,edge + cnt + 1,cmp);  //按照边长排序
    
    for(int i = 1; i <= N; i ++) p[i] = i; //并查集初始化
    
    int k = N; 一共连接N-1次 所以在k=1时退出
    for(int i = 1; i <= cnt; i ++)
    {
        if(k == 1) break;  //图已连成
        int a,b;
        double w;
        a = edge[i].a, b = edge[i].b, w = edge[i].w; 
        if(find(a) == find(b)) continue;  //已经联通就不处理了
        p[find(a)] = b;
        k--;
        if(w > MAX) MAX = w;  //其实没必要if因为边长是递增的
    }
    
    
    for(int i = 1; i <= M; i ++)
      if(leap[i] >= MAX) num++; 
    
    printf("%d",num);
    
    return 0;
    
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Silver_Bullet14

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值