一道图论一(最小生成树kruskal)

文章介绍了一个基于Kruskal算法的解决方案,用于计算给定图中从s到t的路径中单边长度最大值的最小值。通过遍历边并合并最小生成树来实现。

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

给定一个包含 n  个节点和 m  条边的图,每条边有一个权值。
你的任务是回答 k 个询问,每个询问包含两个正整数 s  和 t 表示起点和终点,要求寻找从 s 到 t  的一条路径,使得路径上权值最大的一条边权值最小。

Input

第一行包含三个整数 n 、m 、k ,分别表示 n 个节点, m  条路径, k  个询问。

接下来 m  行,每行三个整数 u , v  , w, 表示一个由 u 到 v  的长度为 w  的双向边。

再接下来 k  行,每行两个整数 s  , t,表示询问从 s 连接到 t  的所有路径中单边长度最大值的最小值。

Output

输出包含 k  行,每一行包含一个整数 p 。p  表示 s  连接到 t 的所有路径中单边长度最大值的最小值。另外,如果 s 到 t  没有路径相连通,输出 -1 即可。

Sample Input

8 11 3
1 2 10
2 5 50
3 4 60
7 5 60
3 6 30
1 5 30
6 7 20
1 7 70
2 3 20
3 5 40
2 6 90
1 7
2 8
6 2

Sample Output

30
-1
30

思路:

这道题最初没想到用最小生成树,看了题解才发现kruskal居然还有这用途,让边从小到大排序,之后一个一个加边,如果两条边通过当前边而连接,说明此边边权即为让两点相连单边长度最大值的最小值。

代码:

#define _CRT_SECURE_NO_WARNINGS 
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<string>
#include<cstring>
#include<cmath>
#include<ctime>
#include<algorithm>
#include<utility>
#include<stack>
#include<queue>
#include<vector>
#include<set>
#include<math.h>
#include<map>
using namespace std;
const int N = 1e5;
struct edge
{
    int x;
    int y;
    int w;

}eg[N];
struct data
{
    int x;
    int y;

}qur[1100];
int  cnt = 0;
int n, m, k, f[1100], ans[1100];
int father(int x)
{
    if (x != f[x]) f[x] = father(f[x]);
    return f[x];
}
bool cmp(const struct edge& a, const struct edge& b)
{
    return a.w < b.w;
}
int main()
{
    cin >> n >> m >> k;
    for (int i = 1; i <= n; i++)
        f[i] = i;
    for (int i = 1; i <= m; i++)
    {
        int x, y, w;
        scanf("%d%d%d", &x, &y, &w);
        eg[i].x = x;
        eg[i].y = y;
        eg[i].w = w;
    }
    for (int i = 1; i <= k; i++)
    {
        int x, y;
        scanf("%d%d", &x, &y);
        qur[i].x = x;
        qur[i].y = y;
    }
    sort(eg + 1, eg + 1 + m, cmp);
    int fa, fb;
    for (int i = 1; i <= m && cnt < n - 1; i++)
    {
        fa = father(eg[i].x);
        fb = father(eg[i].y);

        if (fa == fb) continue;
        for (int j = 1; j <= k; j++)
        {
            if (ans[j]) continue;
            int fx = father(qur[j].x), fy = father(qur[j].y);
            if ((fx == fa && fy == fb) || (fx == fb && fy == fa))
                ans[j] = eg[i].w;
        }
        f[fa] = fb;
        cnt++;
    }
    for (int i = 1; i <= k; i++)
    {
        if (ans[i])
            printf("%d\n", ans[i]);
        else
            printf("-1\n");
    }
    return 0;
}
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值