• 【NOI2014】魔法森林


    Description

    给定一张无向图,边有a,b两种边权,求一条1~n的路径,使得路径上a最大值与b最大值之和尽可能小

    Solution

    LCT维护生成树

    将边按照a从小到大排序,然后顺序考虑每一条边

    如果当前这条边的两个端点没有联通,那么直接在LCT上连边即可

    如果当前这条边的两个端点已经连通,那么在LCT上找到这两点之间b值最大的一条边,若这条边的b值大于当前这条边那么将那条边断掉换成当前边

    在任意时刻,若1与n联通,那么直接更新答案

    Code

      1 #include <bits/stdc++.h>
      2 using namespace std;
      3 inline int read() {
      4     int ret = 0, op = 1;
      5     char c = getchar();
      6     while (!isdigit(c)) {
      7         if (c == '-') op = -1; 
      8         c = getchar();
      9     }
     10     while (isdigit(c)) {
     11         ret = (ret << 3) + (ret << 1) + c - '0';
     12         c = getchar();
     13     }
     14     return ret * op;
     15 }
     16 const int N = 200010;
     17 const int S = 131072;
     18 int n, m, s[N];
     19 struct Edge {
     20     int from, to, da, db;
     21     bool operator <(const Edge &x) const {
     22         return da < x.da;
     23     }
     24 } e[N];
     25 struct LCT {
     26     int fa, val, ch[2], maxx, tag;
     27 } a[N];
     28 inline int isnroot(int now) {
     29     return a[a[now].fa].ch[0] == now || a[a[now].fa].ch[1] == now;
     30 }
     31 inline void update(int now) {
     32     int l = a[now].ch[0];
     33     int r = a[now].ch[1];
     34     a[now].maxx = now;
     35     if (e[a[l].maxx].db > e[a[now].maxx].db) a[now].maxx = a[l].maxx;
     36     if (e[a[r].maxx].db > e[a[now].maxx].db) a[now].maxx = a[r].maxx;
     37 }
     38 inline void rev(int now) {
     39     swap(a[now].ch[0], a[now].ch[1]);
     40     a[now].tag ^= 1;
     41 }
     42 inline void pushdown(int now) {
     43     if (a[now].tag) {
     44         if (a[now].ch[0]) rev(a[now].ch[0]);
     45         if (a[now].ch[1]) rev(a[now].ch[1]);
     46         a[now].tag = 0;
     47     }
     48 }
     49 void rotate(int x) {
     50     int y = a[x].fa;
     51     int z = a[y].fa;
     52     int xson = a[y].ch[1] == x;
     53     int yson = a[z].ch[1] == y;
     54     int B = a[x].ch[xson ^ 1];
     55     if (isnroot(y)) a[z].ch[yson] = x;
     56     a[x].ch[xson ^ 1] = y;
     57     a[y].ch[xson] = B;
     58     if (B) a[B].fa = y;
     59     a[y].fa = x;
     60     a[x].fa = z;
     61     update(y);
     62 }
     63 void splay(int x) {
     64     int y = x, z = 0;
     65     s[++z] = y;
     66     while (isnroot(y)) y = a[y].fa, s[++z] = y;
     67     while (z) pushdown(s[z--]);
     68     while (isnroot(x)) {
     69         y = a[x].fa;
     70         z = a[y].fa;
     71         if (isnroot(y))
     72             (a[z].ch[0] == y) ^ (a[y].ch[0] == x) ? rotate(x) : rotate(y);
     73         rotate(x);
     74     }
     75     update(x);
     76 }
     77 void access(int x) {
     78     for (register int y = 0; x; y = x, x = a[x].fa) {
     79         splay(x); a[x].ch[1] = y; update(x);
     80     }
     81 }
     82 void makeroot(int x) {
     83     access(x);
     84     splay(x);
     85     rev(x);
     86 }
     87 int findroot(int x) {
     88     access(x); splay(x);
     89     while (a[x].ch[0]) pushdown(x), x = a[x].ch[0];
     90     return x;
     91 }
     92 void link(int i) {
     93     makeroot(e[i].to);
     94     a[e[i].to].fa = i;
     95     a[i].fa = e[i].from;
     96 }
     97 void cut(int i) {
     98     access(i); splay(i);
     99     a[a[i].ch[0]].fa = a[a[i].ch[1]].fa = 0;
    100     a[i].ch[0] = a[i].ch[1] = 0;
    101     update(i);
    102 }
    103 int main() {
    104     n = read(); m = read();
    105     for (register int i = 1; i <= m; ++i) {
    106         e[i].from = read() | S; e[i].to = read() | S; e[i].da = read(); e[i].db = read();
    107     }
    108     sort(e + 1, e + m + 1);
    109     int ans = 2147483647;
    110     for (register int i = 1; i <= m; ++i) {
    111         int x = e[i].from, y = e[i].to;
    112         if (x == y) continue ;
    113         makeroot(x);
    114         if (x != findroot(y)) link(i);
    115         else if (e[i].db < e[a[y].maxx].db) cut(a[y].maxx), link(i);
    116         makeroot(1 | S);
    117         if ((1 | S) == findroot(n | S)) ans = min(ans, e[i].da + e[a[n | S].maxx].db);
    118     }
    119     printf("%d
    ", ans == 2147483647 ? -1 : ans);
    120     return 0;
    121 }
    AC Code
  • 相关阅读:
    Exception in thread "main" com.sun.xml.internal.ws.streaming.XMLStreamReaderException: unexpected XML tag.
    Navicat的快捷键
    win7虚拟机起不来,报错transport vmdb error -44 message the vmware authorization
    fedora19配置 SSH 免密码登陆
    Linux下Django的安装
    linux下为用户添加sudo命令功能
    ubuntu修改系统环境变量文件导致起不来
    fedorea19安装redis
    java下载csv文件,中文标题
    POJ A Simple Problem with Integers | 线段树基础练习
  • 原文地址:https://www.cnblogs.com/shl-blog/p/11356081.html
Copyright © 2020-2023  润新知