KD-Graph

这篇博客介绍了如何在一个带有nnn个点和mmm条边的图中,将其分成kkk组,确保同一组内任意两点间存在不超过D的最长路径。通过优先合并边权较小且不在同一组的节点,直至达到目标组数。代码实现展示了使用并查集和排序策略求解这一问题的过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目:

链接

题意:
总共有 n n n 个点, m m m条边,要分成 k k k 组,满足

( 1 ) (1) (1) 如果顶点 p 和 q ( p ≠ q ) 在同一组中,则 p 和 q 之间必须至少有一条路径满足该路径中的最大值小于或等于 D。

( 2 ) (2) (2) 如果顶点 p 和 q ( p ≠ q ) 在不同的组中,则 p 和 q 之间不可能有任何路径满足该路径中的最大值小于或等于 D。

题解:
最开始分为 c n t = n cnt=n cnt=n个组

按找点的边权从小到大排序, 如果这两个点不在同一个集合中,则将它们合并到一个集合中,同时 c n t − = 1 cnt-=1 cnt=1,(减少了只有一个点的组), 当 c n t = k cnt=k cnt=k的时候, D D D为当前的边权值,否则为 − 1 -1 1

注意为了满足要求(2),只有当当前边权不等于上一个边权的时候才判断 c n t cnt cnt是否等于 k k k

#include <bits/stdc++.h>
using namespace std;
struct node {
    long long u,v,w;
}e[500005];
int p[100005];
bool cmp(node a,node b)
{
    return a.w<b.w;
}
int find(int x)
{
    if(p[x]!=x) p[x]=find(p[x]);
    return p[x];
}
int main()
{
    ios::sync_with_stdio(false);cin.tie(0),cout.tie(0);
    int t;
    cin>>t;
    while(t--)
    {
        int n,m,k;
        cin>>n>>m>>k;
        int ans=0;
        int con=n;
        for(int i=1;i<=n;i++) p[i]=i;
        for(int i=1;i<=m;i++)
        {
            cin>>e[i].u>>e[i].v>>e[i].w;
        }
        sort(e+1,e+1+m,cmp);
        for(int i=1;i<=m;i++)
        {
            if(e[i].w!=e[i-1].w)//满足要求(2)
            {
                if(con==k)
                {
                    break;
                }
            }
            int pa=find(e[i].u);
            int pb=find(e[i].v);
            if(pa==pb) continue;
            con--;
            p[pa]=pb;
            ans=e[i].w;//D为当前的边权值
        }
        if(con==k) cout<<ans<<endl;
        else cout<<-1<<endl;
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值