• BZOJ1050旅游


    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不可能相同。
    Output
    如果景点s到景点t没有路径,输出“IMPOSSIBLE”。否则输出一个数,表示最小的速度比。如果需要,输出一个既约分数。

    样例输入1
    4 2
    1 2 1
    3 4 2
    1 4
    样例输入2
    3 3
    1 2 10
    1 2 5
    2 3 8
    1 3
    样例输入3
    3 2
    1 2 2
    2 3 4
    1 3

    样例输出1
    IMPOSSIBLE
    样例输出2
    5/4
    样例输出3
    2

    数据范围
    1<  N < = 500
    1 < = x, y < = N,0 < v < 30000,x ≠ y
    0 < M < =5000

    分析:这道题,从题解上找到了一种思路,即先排序。从起点开始选择边,一直到到达终点。再反向从终点添加边到起点。显然这样的话起点会不断提前。最终起点不能再提前的时候集合中的两条边就是答案。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    
    struct node{
        int x,y,w;
    }e[5001];
    
    int n,m;
    int s,t;
    int fa[501];
    
    bool cmp(node a,node b)
    {
        return a.w<b.w;
    }
    
    int find(int x)
    {
        return fa[x]==x?x:fa[x]=find(fa[x]);
    }
    
    int gcd(int a,int b)
    {
        int r;
        while(b>0)
        {
             r=a%b;
             a=b;
             b=r;
        }
        return a;
    }
    
    int main()
    {
        
        cin >> n >> m;
        for (int i=1; i<=m; i++) cin >> e[i].x >> e[i].y >> e[i].w;
        cin >> s >> t;
        sort(e+1,e+m+1,cmp);
        int f=1;
        int ansmx=0,ansmn=0;
        int mx=0,mn=0;
        while (f<m)
        {
            mx=0; mn=0;
            for (int i=1; i<=n; i++) fa[i]=i;
            while (f<=m) 
            {
                int fx=find(e[f].x),fy=find(e[f].y);
                fa[fx]=fy;
                if (find(s)==find(t)) { mx=e[f].w; break; }
                f++;
            }
            if (mx==0) 
                if (!ansmx) { cout << "IMPOSSIBLE" << endl; return 0; }//找不到从s到t的路 
                    else break;
            for (int i=1; i<=n; i++) fa[i]=i;//初始化 
            while (f>=0)
            {
                int fx=find(e[f].x),fy=find(e[f].y);
                fa[fy]=fx;
                if (find(s)==find(t)) { mn=e[f].w; break; }
                f--; 
            }
            if (mn==0) 
                if (!ansmn) { cout << "IMPOSSIBLE" << endl; return 0; }
                    else break;
            f++;//从下一条边开始枚举 
            int r=gcd(mx,mn);
            mx/=r; mn/=r;//约分 
            if (mx*ansmn<mn*ansmx || (!ansmx && !ansmn)) { ansmx=mx; ansmn=mn; }
        }
        if (ansmn==1) cout << ansmx;
            else cout << ansmx << '/' << ansmn << endl;
        return 0;
    }
  • 相关阅读:
    关于链表
    Linux操作系统(3):crond 任务调度
    高速信号的确定
    python 多线程 QTimer定时自动重复执行某个函数,QSS应用
    使用qtawesome这个第三方库来实现按钮中的Font Awesome字体图标的显示,叠层显示,多窗口显示,窗口禁止缩放,最大化,tap widget使用,按键颜色,建立相关文件路径,点击主窗口退出程序
    IP,子网掩码,网关,DNS的关系解析
    ZLAN6042使用源码(modbus-tcp)
    模块cv2的用法
    python(如何将数据写入本地txt文本文件)
    你猜我猜的经验-电源
  • 原文地址:https://www.cnblogs.com/Shymuel/p/4394267.html
Copyright © 2020-2023  润新知