zoukankan      html  css  js  c++  java
  • [HAOI2006] 旅行

    传送门:>HERE<

    题意:给出一副无向图,求从S到T的任意一条路径中,最大边权与最小边权比值的最小值

    解题思路:

      由于数据范围很小,可以考虑$O(m^2)$的算法。

      刚开始一直很困惑,不就跑一边求一个最大最小比一比吗,为什么还有最小值?太thick了,作为一个无向图,只要两点连通,路径可能多到不知哪里去了。而最大最小值是在同一条路径上的。那么如果Dfs呢,又太慢了。

      我们考虑,如果路径上的最小值已经确定了,那么只要找到剩余路径中最小的最大值就可以了。这好像让我们联想到了Kruscal算法——将所有边排序,枚举最小值(其实就是排序后一条一条枚举)。选定了每一条最小边以后,一条条将剩余的比它大的边插入,直到S和T连通为止——此时的边权一定是最小的最大值了。(单调)。这个过程用并查集就行了。

      再加上一点分数的处理。复杂度大约$O(m^2 log n)$

    Code

    /*By QiXingzhi*/
    #include <cstdio>
    #include <queue>
    #include <cstdlib>
    #include <algorithm>
    #define  r  read()
    #define  Max(a,b)  (((a)>(b)) ? (a) : (b))
    #define  Min(a,b)  (((a)<(b)) ? (a) : (b))
    using namespace std;
    typedef unsigned long long ll;
    const int N = 510;
    const int M = 5010;
    const int INF = 1061109567;
    inline int read(){
        int x = 0; int w = 1; register int c = getchar();
        while(c ^ '-' && (c < '0' || c > '9')) c = getchar();
        if(c == '-') w = -1, c = getchar();
        while(c >= '0' && c <= '9') x = (x << 3) +(x << 1) + c - '0', c = getchar();
        return x * w;
    }
    struct Edge{ int u,v,w; }a[M];
    struct Frac{ int x,y; }ans;
    int n,m,x,y,z,S,T,par[N];
    inline bool FracCompare(Frac _a, Frac _b){ return !(_a.x * _b.y < _b.x * _a.y); }
    int gcd(int a, int b){ return !b ? a : gcd(b, a%b); }
    inline void PrintAns(Frac __a){
        int g = gcd(__a.x, __a.y);
        __a.x /= g, __a.y /= g;
        if(__a.y == 1){ printf("%d",__a.x);
        else printf("%d/%d",__a.x, __a.y);
    }
    inline bool comp(const Edge& a, const Edge& b){ return a.w < b.w; }
    int find(int x){ return par[x] == x ? x : par[x] = find(par[x]); }
    inline void Try(int _t){
        for(int i = 1; i <= n; ++i) par[i] = i;
        int A,B,__max=-1;
        for(int i = _t; i <= m; ++i){
            A = find(a[i].u), B = find(a[i].v);
            if(A != B) par[A] = B;
            if(find(S) == find(T)){ __max = a[i].w; break; }
        }
        if(__max != -1){
            Frac _tmp1; _tmp1.x = __max, _tmp1.y = a[_t].w;
            if(FracCompare(_tmp1, ans) == 0) ans = _tmp1;
        }
    }
    inline void JudgeConnect(){
        int A,B;
        for(int i = 1; i <= n; ++i) par[i] = i;
        for(int i = 1; i <= m; ++i){
            A = find(a[i].u), B = find(a[i].v);
            if(A != B) par[A] = B;
        }
        if(find(S) != find(T)) printf("IMPOSSIBLE"), exit(0);
    }
    int main(){
        n = r, m = r;
        for(int i = 1; i <= m; ++i) a[i].u = r, a[i].v = r, a[i].w = r;
        S = r, T = r;
        sort(a+1, a+m+1, comp);
        JudgeConnect();
        ans.x = INF; ans.y = 1;
        for(int i = 1; i <= m; ++i) Try(i);
        PrintAns(ans);
        return 0;
    }
  • 相关阅读:
    ABP官方文档翻译 3.4 领域服务
    ABP官方文档翻译 3.3 仓储
    ABP官方文档翻译 3.2 值对象
    ABP官方文档翻译 3.1 实体
    ABP官方文档翻译 2.7 对象到对象的映射
    ABP官方文档翻译 2.6 定时
    bootstrap 源码中部分不了解的css属性
    vue 父组件调用子组件事件/子组件调用父组件方法
    js性能优化问题学习笔记
    js递归性能影响及解决方案
  • 原文地址:https://www.cnblogs.com/qixingzhi/p/9341575.html
Copyright © 2011-2022 走看看