1050:[HAOI2006]旅行comf

来源:互联网 发布:蒸汽巴士推荐的淘宝店 编辑:程序博客网 时间:2024/05/22 23:51

题目链接

题目大意:给定无向图,求所有从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;}
0 0
原创粉丝点击