bzoj 1050: [HAOI2006]旅行comf

Description

给你一个无向图,N(N<=500)个顶点, M(M<=5000)条边,每条边有一个权值Vi(Vi<30000)。给你两个顶点S和T,求

一条路径,使得路径上最大边和最小边的比值最小。如果S和T之间没有路径,输出”IMPOSSIBLE”,否则输出这个

比值,如果需要,表示成一个既约分数。 备注: 两个顶点之间可能有多条路径。

解:

题目要求一条s-->t的路径满足最大值和最小值之间的比例最小。

1、想到枚举最大值找最小值最大or  枚举最小值找最大值最小

2、对边排序,枚举最大边,跑最大生成树,求出比值里最小的

#include<stdio.h>
#include<iostream>
#include<string.h>
#include<algorithm>
using namespace std;
#define ll long long
#define en '\n'
const int maxn =5e3+10;
const int inf=0x3f3f3f3f;
inline int read(){
	int x=0,f=1;  char ch=getchar();
	while(!isdigit(ch))  {if(ch=='-')  f=-1;  ch=getchar();}
	while(isdigit(ch))  {x=x*10+ch-'0';  ch=getchar();}
	return x*f;
}
int n,m,s,t;
struct node{
ll x,y,w;
bool operator <(const node &b)const{
    return w<b.w;
}
}edge[maxn];
bool v[maxn];
int f[maxn];
ll gcd(ll a,ll b){
if(b==0)return a;return gcd(b,a%b);
}
int find(int x){
return x==f[x]?x:f[x]=find(f[x]);
}

signed  main()
{
#ifdef local
freopen("input2.txt","r",stdin);
#endif
#define int  register int
        n=read(),m=read();
        for(int i=1;i<=m;i++)edge[i].x=read(),edge[i].y=read(),edge[i].w=read();
        sort(edge+1,edge+1+m);s=read(),t=read();
        ll x=1,y=inf;bool yes=0;ll mx,mi;
        for(int i=1;i<=m;i++){
            for(int j=1;j<=n;j++)f[j]=j;
            mx=edge[i].w;
            for(int j=i;j>=1;--j){
                int xx=find(edge[j].x),yy=find(edge[j].y);
                if(xx==yy)continue;f[xx]=yy;
                mi=edge[j].w;
                if(find(s)==find(t)){yes=1;
                    if(y*mi>x*mx){
                        int tem=gcd(mx,mi);
                        y=mx/tem;x=mi/tem;
                    }
                    break;
                }
            }
        }
        if(!yes)puts("IMPOSSIBLE");
        else {
            if(x==1)cout<<y<<en;
            else
            cout<<y<<'/'<<x<<en;
        }
    return 0;
}

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值