code1001 舒适的路线

n次最小生成树kruskal

将所有的边排序,权值小的在前。

设排序后第i条边为路径中的最长边,那么这条路径一定是由1~i中的一些边组成

因为最高速和最低速的差尽量小,最高速确定了,最低速应尽量大。

所以j从i downto 1,将边j加入边集,如果此时s和t联通了(s t在并查集的一个集合中),那么找到一组可行的解:最大i.w,最小j.w,与最优解比较、更新。

如果还没联通,继续找下一个j。直到j到1还没有,那么说明i为最大边是不行的,i++继续。

 

代码:

#include<iostream>
#include<algorithm>
#define MaxN 505
#define MaxM 5005 
using namespace std;

int n,m;
struct edge{
    int u,v,w;
}eg[MaxM];
bool flag=false;
int ansa=0x3f3f3f3f,ansb=0;
int start,end;

int pa[MaxN];
void init(){
    for(int i=1;i<=n;i++)pa[i]=i;
}
int find(int x){
    if(x!=pa[x])pa[x]=find(pa[x]);
    return pa[x];
}
void un(int x,int y){
    if(find(x)==find(y))return;
    pa[find(x)]=find(y);
}

bool ff(edge a,edge b){
    return a.w<b.w;
}
int gcd(int a,int b){
    return b?gcd(b,a%b):a;
}

void out(int a,int b){
    if((double)a/b < (double)ansa/ansb){
        int t=gcd(a,b);
        ansa=a/t;
        ansb=b/t;
        //cout<<a<<"/"<<b<<"    "<<ansa<<"/"<<ansb<<endl;
    }
}

int main(){
    cin>>n>>m;
    for(int i=1;i<=m;i++){
        scanf("%d%d%d",&eg[i].u,&eg[i].v,&eg[i].w);
    }
    cin>>start>>end;
    
    sort(eg+1,eg+1+m,ff);
    
    for(int i=1;i<=m;i++){
        init();
        for(int j=i;j>=1;j--){
            un(eg[j].u,eg[j].v);
            if(find(start)==find(end)){
                out(eg[i].w,eg[j].w);
                flag=true;
            }
        }
    }
    if(flag){
        cout<<ansa;
        if(ansb!=1)cout<<'/'<<ansb;
    }
    else cout<<"IMPOSSIBLE";
    return 0;
}

 

转载于:https://www.cnblogs.com/FuTaimeng/p/5611832.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值