zoukankan      html  css  js  c++  java
  • 【BZOJ1050】[HAOI2006]旅行comf

    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不可能相同。
    1<N<=500,1<=x,y<=N,0<v<30000,0<M<=5000

    Output

      如果景点s到景点t没有路径,输出“IMPOSSIBLE”。否则输出一个数,表示最小的速度比。如果需要,输出一
    个既约分数。

    Sample Input

    【样例输入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

    Sample Output

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

    Solution

    两种做法:

    1. O(m^2)的暴力

    我们发现一个性质:答案一定是排序后一个后缀的最小生成树。所以暴力就是直接枚举每个后缀跑最小生成树。

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <algorithm>
     4 #include <cmath>
     5 
     6 #ifdef WIN32
     7     #define LL "%I64d"
     8 #else
     9     #define LL "%lld"
    10 #endif
    11 
    12 #ifdef CT
    13     #define debug(...) printf(__VA_ARGS__)
    14     #define setfile() 
    15 #else
    16     #define debug(...)
    17     #define filename ""
    18     #define setfile() freopen(filename".in", "r", stdin); freopen(filename".out", "w", stdout)
    19 #endif
    20 
    21 #define R register
    22 #define getc() (S == T && (T = (S = B) + fread(B, 1, 1 << 15, stdin), S == T) ? EOF : *S++)
    23 #define dmax(_a, _b) ((_a) > (_b) ? (_a) : (_b))
    24 #define dmin(_a, _b) ((_a) < (_b) ? (_a) : (_b))
    25 #define cmax(_a, _b) (_a < (_b) ? _a = (_b) : 0)
    26 #define cmin(_a, _b) (_a > (_b) ? _a = (_b) : 0)
    27 #define cabs(_x) ((_x) < 0 ? (- (_x)) : (_x))
    28 char B[1 << 15], *S = B, *T = B;
    29 inline int F()
    30 {
    31     R char ch; R int cnt = 0; R bool minus = 0;
    32     while (ch = getc(), (ch < '0' || ch > '9') && ch != '-') ;
    33     ch == '-' ? minus = 1 : cnt = ch - '0';
    34     while (ch = getc(), ch >= '0' && ch <= '9') cnt = cnt * 10 + ch - '0';
    35     return minus ? -cnt : cnt;
    36 }
    37 #define maxn 510
    38 #define maxm 5010
    39 struct Edge
    40 {
    41     int a, b, w;
    42     inline bool operator < (const Edge &that) const {return w < that.w;}
    43 }e[maxm];
    44 int Fa[maxn], n, m;
    45 inline void init()
    46 {
    47     for (R int i = 1; i <= n; ++i) Fa[i] = i;
    48 }
    49 int gcd(R int a, R int b) {return !b ? a : gcd(b, a % b);}
    50 int Find(R int x) {return Fa[x] == x ? x : Fa[x] = Find(Fa[x]);}
    51 int main()
    52 {
    53 //    setfile();
    54     n = F(), m = F();
    55     for (R int i = 1; i <= m; ++i)
    56         e[i] = (Edge) {F(), F(), F()};
    57     R int s = F(), t = F();
    58     std::sort(e + 1, e + m + 1);
    59     R int ans1 = 1, ans2 = 0;
    60     for (R int i = 1; i <= m; ++i)
    61     {
    62         init();
    63         R int up;
    64         R bool flag = 1;
    65         for (R int j = i; j <= m && flag; ++j)
    66         {
    67             R int f1 = Find(e[j].a), f2 = Find(e[j].b);
    68             if (f1 != f2) Fa[f1] = f2;
    69             if (Find(s) == Find(t)) flag = 0, up = e[j].w;
    70         }
    71         if (i == 1 && flag) return puts("IMPOSSIBLE"), 0;
    72         if (!flag && (double) up / e[i].w < (double) ans1 / (double) ans2)
    73         {
    74             ans1 = up;
    75             ans2 = e[i].w;
    76         }
    77     }
    78     if (ans1 % ans2 == 0) printf("%d
    ", ans1 / ans2 );
    79     else printf("%d/%d
    ", ans1 / gcd(ans1, ans2), ans2 / gcd(ans1, ans2) );
    80     return 0;
    81 }
    m^2

    2.O(mlogm)

    既然不能暴力做最小生成树,那就用LCT维护最小生成树即可。

      1 #include <cstdio>
      2 #include <algorithm>
      3 
      4 #define R register
      5 #define inf 0x7fffffff
      6 #define maxn 100010
      7 #define maxm 200010
      8 struct ed{
      9     int a, b, w;
     10     inline bool operator < (const ed &that) const {return w < that.w;} 
     11 }e[maxm];
     12 struct node *null;
     13 struct node
     14 {
     15     node *ch[2], *fa, *pos;
     16     int val, mn;
     17     bool rev;
     18     inline bool type()
     19     {
     20         return fa -> ch[1] == this;
     21     }
     22     inline bool check()
     23     {
     24         return fa -> ch[type()] == this;
     25     }
     26     inline void pushup()
     27     {
     28         pos = this; mn = val;
     29         ch[0] -> mn < mn ? mn = ch[0] -> mn, pos = ch[0] -> pos : 0;
     30         ch[1] -> mn < mn ? mn = ch[1] -> mn, pos = ch[1] -> pos : 0;
     31     }
     32     inline void pushdown()
     33     {
     34         if (rev)
     35         {
     36             ch[0] -> rev ^= 1;
     37             ch[1] -> rev ^= 1;
     38             std::swap(ch[0], ch[1]);
     39             rev ^= 1;
     40         }
     41     }
     42     inline void pushdownall()
     43     {
     44         if (check()) fa -> pushdownall();
     45         pushdown();
     46     }
     47     inline void rotate()
     48     {
     49         R bool d = type(); R node *f = fa, *gf = f -> fa;
     50         (fa = gf, f -> check()) ? fa -> ch[f -> type()] = this : 0;
     51         (f -> ch[d] = ch[!d]) != null ? (ch[!d] -> fa = f) : 0;
     52         (ch[!d] = f) -> fa = this;
     53         f -> pushup();
     54     }
     55     inline void splay(R bool npda = 1)
     56     {
     57         if (npda) pushdownall();
     58         for (; check(); rotate())
     59             if (fa -> check())
     60             {
     61                 if (type() == fa -> type()) fa -> rotate();
     62                 else rotate();
     63             }
     64         pushup();
     65     }
     66     inline node *access()
     67     {
     68         R node *i = this, *j = null;
     69         for ( ; i != null; i = (j = i) -> fa)
     70         {
     71             i -> splay();
     72             i -> ch[1] = j;
     73             i -> pushup();
     74         }
     75         return j;
     76     }
     77     inline void make_root()
     78     {
     79         access(); splay(); rev ^= 1;
     80     }
     81     inline void link(R node *that)
     82     {
     83         make_root();
     84         fa = that;
     85         splay(0);
     86     }
     87     inline void cut(R node *that)
     88     {
     89         make_root();
     90         that -> access();
     91         that -> splay(0);
     92         that -> ch[0] = fa = null;
     93         that -> pushup();
     94     }
     95 }mem[1000010], *ncnt = mem, *edge = mem + 100010;
     96 int gcd(R int a, R int b)
     97 {
     98     return b ? gcd(b, a % b) : a;
     99 }
    100 inline node *query(node *a, node *b)
    101 {
    102     a -> make_root();
    103     b -> access(); b -> splay(0);
    104     return b -> pos;
    105 }
    106 int Fa[maxn], m, n;
    107 int Find(R int x) {return Fa[x] == x ? x : Fa[x] = Find(Fa[x]);}
    108 int main()
    109 {
    110     null = mem;
    111     *null = (node) {{null, null}, null, null, inf, inf, 0};
    112     scanf("%d%d", &n, &m);
    113     for (R int i = 1; i <= m; ++i) scanf("%d%d%d", &e[i].a, &e[i].b, &e[i].w);
    114     R int s, t; scanf("%d%d", &s, &t);
    115     std::sort(e + 1, e + m + 1);
    116     R int up = 1, down = 0;
    117     for (R int i = 1; i <= n; ++i)
    118     {
    119         Fa[i] = i;
    120         mem[i] = (node) {{null, null}, null, null, inf, inf, 0};
    121     }
    122     R int con = 0;
    123     for (R int i = 1; i <= m; ++i)
    124     {
    125         R int mi, a = e[i].a, b = e[i].b;
    126         if (a == b) continue;
    127         R int f1 = Find(a), f2 = Find(b);
    128         *(edge + i) = (node) {{null, null}, null, null, e[i].w, e[i].w, 0};
    129         if (f1 != f2)
    130         {
    131             Fa[f1] = f2;
    132             (mem + a) -> link(edge + i);
    133             (mem + b) -> link(edge + i);
    134             ++con;
    135         }
    136         else
    137         {
    138             R node *p = query(mem + a, mem + b);
    139             (mem + e[p - edge].a) -> cut(p);
    140             (mem + e[p - edge].b) -> cut(p);
    141             (mem + a) -> link(edge + i);
    142             (mem + b) -> link(edge + i);
    143         }
    144         if (Find(s) == Find(t))
    145         {
    146             mi = query(mem + s, mem + t) -> val;
    147             // 从s到t的链上最小值。
    148             if (1ll * up * mi > 1ll * e[i].w * down)
    149             {
    150                 up = e[i].w;
    151                 down = mi;
    152             }
    153         }
    154     }
    155     if (down == 0) puts("IMPOSSIBLE");
    156     else if (up % down == 0) printf("%d
    ", up / down);
    157     else printf("%d/%d
    ", up / gcd(up, down), down / gcd(up, down));
    158     return 0;
    159 }
    mlogm
  • 相关阅读:
    前端3 浮动布局,固定定位,绝对定位,相对定位
    前端2 字体|文本属性样式, 高级选择器
    前端1.概念
    前端,基础选择器,嵌套关系.display属性,盒模型
    数据库之索引
    数据库之进阶(视图,事务,存储过程)
    数据库,多表数据
    数据库之表的使用
    数据的演化(数据仓库的发展史)
    HDFS退出安全模式
  • 原文地址:https://www.cnblogs.com/cocottt/p/6618952.html
Copyright © 2011-2022 走看看