• 洛谷 2387/BZOJ 3669 魔法森林


    3669: [Noi2014]魔法森林

    Time Limit: 30 Sec  Memory Limit: 512 MB
    Submit: 3765  Solved: 2402
    [Submit][Status][Discuss]

    Description

    为了得到书法大家的真传,小E同学下定决心去拜访住在魔法森林中的隐士。魔法森林可以被看成一个包含个N节点M条边的无向图,节点标号为1..N,边标号为1..M。初始时小E同学在号节点1,隐士则住在号节点N。小E需要通过这一片魔法森林,才能够拜访到隐士。

    魔法森林中居住了一些妖怪。每当有人经过一条边的时候,这条边上的妖怪就会对其发起攻击。幸运的是,在号节点住着两种守护精灵:A型守护精灵与B型守护精灵。小E可以借助它们的力量,达到自己的目的。

    只要小E带上足够多的守护精灵,妖怪们就不会发起攻击了。具体来说,无向图中的每一条边Ei包含两个权值Ai与Bi。若身上携带的A型守护精灵个数不少于Ai,且B型守护精灵个数不少于Bi,这条边上的妖怪就不会对通过这条边的人发起攻击。当且仅当通过这片魔法森林的过程中没有任意一条边的妖怪向小E发起攻击,他才能成功找到隐士。

    由于携带守护精灵是一件非常麻烦的事,小E想要知道,要能够成功拜访到隐士,最少需要携带守护精灵的总个数。守护精灵的总个数为A型守护精灵的个数与B型守护精灵的个数之和。

    Input

    第1行包含两个整数N,M,表示无向图共有N个节点,M条边。 接下来M行,第行包含4个正整数Xi,Yi,Ai,Bi,描述第i条无向边。其中Xi与Yi为该边两个端点的标号,Ai与Bi的含义如题所述。 注意数据中可能包含重边与自环。 

    Output

    输出一行一个整数:如果小E可以成功拜访到隐士,输出小E最少需要携带的守护精灵的总个数;如果无论如何小E都无法拜访到隐士,输出“-1”(不含引号)。

    Sample Input

    【输入样例1】
    4 5
    1 2 19 1
    2 3 8 12
    2 4 12 15
    1 3 17 8
    3 4 1 17
     
    【输入样例2】
    3 1
    1 2 1 1

    Sample Output

    【输出样例1】
    32

    【样例说明1】
    如果小E走路径1→2→4,需要携带19+15=34个守护精灵;
    如果小E走路径1→3→4,需要携带17+17=34个守护精灵;
    如果小E走路径1→2→3→4,需要携带19+17=36个守护精灵;
    如果小E走路径1→3→2→4,需要携带17+15=32个守护精灵。
    综上所述,小E最少需要携带32个守护精灵。

    【输出样例2】
    -1

    【样例说明2】
    小E无法从1号节点到达3号节点,故输出-1。

    HINT

    2<=n<=50,000

    0<=m<=100,000

    1<=ai ,bi<=50,000

    题解

    LCT+Kruskal

      1 #include <algorithm>
      2 #include <iostream>
      3 #include <cstring>
      4 #include <cstdio>
      5 #include <cctype>
      6 
      7 inline void read(int & x)
      8 {
      9     x = 0;
     10     int k = 1;
     11     char c = getchar();
     12     while (!isdigit(c))
     13         if (c == '-') c = getchar(), k = -1;
     14         else c = getchar();
     15     while (isdigit(c))
     16         x = (x << 1) + (x << 3) + (c ^ 48),
     17         c = getchar();
     18     x *= k;
     19 }
     20 
     21 const int N = 505050, inf = 2147483645;
     22 int n, m, tot, rt = 0, x, y, A, B, z, top = 0, ans = inf, stk_top = 0, cur;
     23 int faz[N], siz[N], sma[N], tag[N], val[N], cnt[N], son[N][2], fa[N], stk[N], L[N], R[N];
     24 
     25 inline int min(const int &a, const int &b) 
     26 {
     27     return a > b ? b : a;
     28 }
     29 
     30 inline void Swap(int &a, int &b)
     31 {
     32     a ^= b, b ^= a, a ^= b;
     33 }
     34 
     35 inline int Root(int u)
     36 {
     37     return son[faz[u]][0] != u && son[faz[u]][1] != u;
     38 }
     39 
     40 inline int Getson(int u)
     41 {
     42     return son[faz[u]][1] == u;
     43 }
     44 
     45 inline void Pushup(int u)
     46 {
     47     sma[u] = u;
     48     if (val[sma[u]] < val[sma[son[u][0]]]) sma[u] = sma[son[u][0]];
     49     if (val[sma[u]] < val[sma[son[u][1]]]) sma[u] = sma[son[u][1]];
     50 }
     51 
     52 inline void Pushdown(int u)
     53 {
     54     if (!tag[u]) return;
     55     tag[son[u][0]] ^= 1,
     56     tag[son[u][1]] ^= 1,
     57     Swap(son[u][0], son[u][1]);
     58     tag[u] = 0;
     59 }
     60 
     61 inline int New(int x)
     62 {
     63     int u = ++tot;
     64     siz[u] = cnt[u] = 1,
     65     son[u][0] = tag[u] =
     66     faz[u] = son[u][1] = 0,
     67     val[u] = x,    sma[u] = u;
     68     return u;
     69 }
     70 
     71 inline void Ratate(int u)
     72 {
     73     int y = faz[u], z = faz[y], ch = Getson(u), b = son[u][ch ^ 1];
     74     Pushdown(y), Pushdown(u);
     75     if (!Root(y)) son[z][Getson(y)] = u;
     76     son[u][ch ^ 1] = y, son[y][ch] = b,
     77     faz[u] = z, faz[b] = y, faz[y] = u;
     78     Pushup(y), Pushup(u);
     79 }
     80 
     81 inline void Splay(int u)
     82 {
     83     int cur = u;
     84     stk[stk_top = 1] = u;
     85     while (!Root(u)) stk[++stk_top] = u = faz[u];
     86     while (stk_top) Pushdown(stk[stk_top--]);
     87     while (!Root(cur))
     88     {
     89         if (!Root(faz[cur]))
     90             if (Getson(cur) == Getson(faz[cur])) Ratate(faz[cur]);
     91             else Ratate(cur);
     92         Ratate(cur);
     93     }
     94 }
     95 
     96 inline void Access(int u)
     97 {
     98     for (int ch = 0; u; u = faz[ch = u])
     99         Splay(u), son[u][1] = ch, Pushup(u);
    100 }
    101 
    102 inline void Mkrt(int u)
    103 {
    104     Access(u), Splay(u), tag[u] ^= 1;
    105 }
    106 
    107 inline void Split(int x, int y)
    108 {
    109     Mkrt(x), Access(y), Splay(y);
    110 }
    111 
    112 inline void Link(int a, int b)
    113 {
    114     Mkrt(a), faz[a] = b;
    115 }
    116 
    117 inline void Cut(int a, int b)
    118 {
    119     Split(a, b);
    120     if (son[b][0] != a || faz[a] != b) return;
    121     faz[a] = 0, son[b][0] = 0;
    122     Pushup(b);
    123 }
    124 
    125 inline int Get(int a, int b)
    126 {
    127     Split(b, a);
    128     return sma[a];
    129 }
    130 
    131 struct Edge
    132 {
    133     int u, v, a, b;
    134     bool operator < (const Edge &B) const
    135         { return a < B.a; }
    136 }e[505050];
    137 
    138 int Find(int u) 
    139 {
    140     return fa[u] == u ? u : fa[u] = Find(fa[u]);
    141 }
    142 
    143 inline void Uni(int a, int b)
    144 {
    145     int r1 = Find(a),
    146         r2 = Find(b);
    147     if (r1 == r2) return;
    148     fa[r1] = r2;
    149 }
    150 
    151 inline bool Tgt(int a, int b)
    152 {
    153     int r1 = Find(a),
    154         r2 = Find(b);
    155     if (r1 == r2) return true;
    156     return false;
    157 }
    158 
    159 signed main()
    160 {
    161 //     freopen("a.in", "r", stdin);
    162 //     freopen("a.out", "w", stdout);
    163     read(n), read(m);
    164     for (int i = 1; i <= n; ++i) 
    165         fa[i] = i;
    166     for (int i = 1; i <= m; ++i)
    167         read(e[i].u), read(e[i].v),
    168         read(e[i].a), read(e[i].b);
    169     //    puts("");
    170     std::sort(e + 1, e + m + 1);
    171     for (int i = 1; i <= m; ++i)
    172     {
    173         if (Tgt(e[i].u, e[i].v))
    174         {
    175             if (val[z = Get(e[i].u, e[i].v)] > e[i].b)
    176                 Cut(e[z - n].u, z),
    177                 Cut(z, e[z - n].v);
    178             else 
    179             {if (Tgt(1, n)) 
    180                 ans = min(ans, val[Get(1, n)] + e[i].a);
    181                 continue; 
    182             }
    183         }
    184         else Uni(e[i].u, e[i].v);
    185         val[n + i] = e[i].b,
    186         sma[n + i] = n + i,
    187         Link(e[i].u, n + i),
    188         Link(n + i, e[i].v);
    189         if (Tgt(1, n))
    190         ans = min(ans, val[Get(1, n)] + e[i].a);
    191     }
    192     if (ans == inf) puts("-1");
    193     else printf("%d
    ", ans);
    194     return 0;
    195 }
  • 相关阅读:
    转 linux shell自定义函数(定义、返回值、变量作用域)介绍
    转 Shell调试篇
    WIN2012的桌面和开始菜单跑到什么地方去了
    转 awr自动收集脚本
    Troubleshooting Guide for ORA-12541 TNS: No Listener
    test
    向Linus学习,让代码具有good taste
    php 页面展示
    c++ list sort
    c++ word类型
  • 原文地址:https://www.cnblogs.com/yanyiming10243247/p/10057762.html
Copyright © 2020-2023  润新知