1050:[HAOI2006]旅行comf

本文介绍了一种解决特定图论问题的算法——求解从起点到终点所有路径中最大边与最小边比值最小的问题。该算法通过枚举最小边并结合并查集进行维护实现,最终找到最优解。

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

题目链接

题目大意:给定无向图,求所有从s到t的路径中最大边与最小边的比值的最小值

题解:枚举最小边,并查集维护。

我的收获:因为ans只与路径中的边权max和min有关,是双变量优化问题。用常用的枚举其中一个变量的方法就可以通过了

#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
const int M=505;
int n,m,st,ed,mx;
int ans_mi=1,ans_mx=12345;
int f[M*10];

struct edge{int u,v,vl;}e[M*10];

int fid(int x){return f[x]==x?x:f[x]=fid(f[x]);}
bool cmp(edge x,edge y){return x.vl<y.vl;}

void uniom(int u,int v){
    int x=fid(u),y=fid(v);
    if(x!=y) f[x]=y;
}

bool kruskal(int x)
{
    mx=-1;
    for(int i=1;i<=m;i++) f[i]=i;
    for(int i=1;i<=m;i++)
    {
        if(fid(st)==fid(ed)) break;
//s可以到达t,此时的mx即为最大边权
        if(e[i].vl<x) continue;//x为最小边权值,只能选比x大的 
        uniom(e[i].u,e[i].v);
        mx=e[i].vl;
    }
    if(fid(st)==fid(ed)) return true;
    return false;
}

void del(int x)
{
    if(!kruskal(x)) return ;
    if(double(mx)/x<double(ans_mx)/ans_mi)//double/int会变成double 
    ans_mx=mx,ans_mi=x;
    int key=__gcd(ans_mx,ans_mi);//有爱的函数 
    ans_mx/=key,ans_mi/=key;
}

void work()
{
    for(int i=1;i<=m;i++)//枚举最小边 
        del(e[i].vl);
    if(ans_mx==12345) puts("IMPOSSIBLE");//无解 
    else if(ans_mi==1) printf("%d\n",ans_mx);
    else printf("%d/%d\n",ans_mx,ans_mi);
}

void init()
{
    cin>>n>>m;
    for(int i=1;i<=m;i++)
        scanf("%d%d%d",&e[i].u,&e[i].v,&e[i].vl);
    sort(e+1,e+1+m,cmp);
    cin>>st>>ed;
}

int main()
{
    init();
    work();
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值