bzoj 1050 [HAOI2006]旅行comf [最小生成树] [动点spfa] [LCT]

本文针对HAOI2006旅行问题提供了一种解决方案,通过使用图论和算法来寻找两点间最大最小边比值最小的路径。介绍了如何通过SPFA算法和分数比较来解决这一问题。

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

1050: [HAOI2006]旅行comf

Time Limit: 10 Sec Memory Limit: 162 MB
Submit: 2740 Solved: 1486

Description

  给你一个无向图,N(N<=500)个顶点, M(M<=5000)条边,每条边有一个权值Vi(Vi<30000)。给你两个顶点S和T
,求一条路径,使得路径上最大边和最小边的比值最小。如果S和T之间没有路径,输出”IMPOSSIBLE”,否则输出
这个比值,如果需要,表示成一个既约分数。 备注: 两个顶点之间可能有多条路径。

Input

  第一行包含两个正整数,N和M。下来的M行每行包含三个正整数:x,y和v。表示景点x到景点y之间有一条双向
公路,车辆必须以速度v在该公路上行驶。最后一行包含两个正整数s,t,表示想知道从景点s到景点t最大最小速
度比最小的路径。s和t不可能相同。
1

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<vector>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<string>
#include<iomanip>
#include<ctime>
#include<climits>
#include<cctype>
#include<algorithm>
#ifdef WIN32
#define AUTO "%I64d"
#else
#define AUTO "%lld"
#endif
using namespace std;
#define smax(x,tmp) x=max((x),(tmp))
#define smin(x,tmp) x=min((x),(tmp))
#define maxx(x1,x2,x3) max(max(x1,x2),x3)
#define minn(x1,x2,x3) min(min(x1,x2),x3)
typedef long long LL;
const int INF=0x3f3f3f3f;
const int maxn = 505;
const int maxm = 5005;
LL gcd(LL a,LL b)
{
    if(!b) return a;
    return gcd(b,a%b);
}
struct Fraction
{
    LL numer,deno; // numerator/denominator
    void reduce()
    {
        LL GCD = gcd(numer,deno);
        numer/=GCD; deno/=GCD;
    }
    Fraction (const LL a,const LL b) { numer=a,deno=b; reduce();  }
    bool operator < (const Fraction t) const
    {
        LL GCD=gcd(deno,t.deno);
        LL a1=numer*t.deno/GCD;
        LL a2=t.numer*deno/GCD;
        return a1 < a2;
    }
    bool operator == (Fraction t)
    {
        reduce(); t.reduce();
        return numer==t.numer && deno==t.deno;
    }
};
struct Edge
{
    int to,next;
    int val;
}edge[maxm<<1];
int head[maxn];
int maxedge;
inline void addedge(int u,int v,int c)
{
    edge[++maxedge] = (Edge) { v,head[u],c };
    head[u] = maxedge;
    edge[++maxedge] = (Edge) { u,head[v],c };
    head[v] = maxedge;
}
struct Road
{
    int u,v;
    int c;
    bool operator < (const Road t) const { return c > t.c; }
}road[maxm];
int n,m,S,T;
inline void init()
{
    scanf("%d%d",&n,&m);
    memset(head,-1,sizeof(head));
    maxedge=-1;
    for(int i=1;i<=m;i++)
        scanf("%d%d%d",&road[i].u,&road[i].v,&road[i].c);
    sort(road+1,road+m+1); //decending order
    scanf("%d%d",&S,&T);
}
queue <int> que;
bool inque[maxn];
int dis[maxn];
void spfa()
{
    while(!que.empty())
    {
        int u=que.front();que.pop();inque[u]=false;
        for(int i=head[u];~i;i=edge[i].next)
        {
            int v=edge[i].to;
            if(dis[v]>max(dis[u],edge[i].val))
            {
                dis[v]=max(dis[u],edge[i].val);
                if(inque[v]) continue;
                inque[v]=true;
                que.push(v);
            }
        }
    }
}
Fraction work()
{
    Fraction ans=Fraction(INF,1);
    memset(dis,0x3f,sizeof(dis));
    memset(inque,0,sizeof(inque));
    dis[S]=0;
    for(int i=1;i<=m;i++)
    {
        addedge(road[i].u,road[i].v,road[i].c);
        que.push(road[i].u); que.push(road[i].v);
        spfa();
        smin(ans,dis[T]<INF?Fraction(dis[T],road[i].c):Fraction(INF,1));
    }
    return ans;
}
void print(Fraction t)
{
    printf("%d",t.numer);
    if(t.deno^1ll) printf("/%d",t.deno);
    putchar('\n');
}
int main()
{
#ifndef ONLINE_JUDGE
    freopen("comf.in","r",stdin);
    freopen("comf.out","w",stdout);
#endif
    init();
    Fraction ans=work();
    if(ans==Fraction(INF,1)) puts("IMPOSSIBLE");
    else print(ans);
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值