ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

【NOI2014】魔法森林

2019-08-15 09:52:38  阅读:200  来源: 互联网

标签:maxx ch int void 魔法 NOI2014 fa now 森林


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\n", ans == 2147483647 ? -1 : ans);
120     return 0;
121 }
AC Code

 

标签:maxx,ch,int,void,魔法,NOI2014,fa,now,森林
来源: https://www.cnblogs.com/shl-blog/p/11356081.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有