zoukankan      html  css  js  c++  java
  • bzoj 3669: [Noi2014]魔法森林 (LCT & kruskal)

    这道题呢,

    首先按照关键字a排序,然后不断地加边,用lct维护这个过程

    具体实现: 先按照关键字a排序,枚举每一条边,判断两点是否已经联通(kruskal 部分)如果联通,就在两点路径间寻找最大的b, 和这条边的b值相比较,如果更大一些,就切断u,v之间的路径, 并连上这条边;

    如果不联通,就让它联通(好随意啊= =

    最后寻找路径之间最大的b + 当前的a,和原来的答案相比较。

    剩下的用lct维护

    注意联通的方式是把把边看做点, 然后连接(所以加上n)   ->link(u, i + n);  link(v, i + n);

    (由于我一直不理解怎么保证当前的a一定在路径上,所以这是自己yy的证明(可能有很大的bug,勿喷):当前的a如果不在(1,n)路径之中,但(1,n)已联通,那么最优值在之前已经被计算过,否则由于a是递增的,那么此时的a就是路径中最大的a)

    下面是代码

      1 /**************************************************************
      2     Problem: 3669
      3     User: cminus
      4     Language: C++
      5     Result: Accepted
      6     Time:5104 ms
      7     Memory:6128 kb
      8 ****************************************************************/
      9  
     10 #include <cstdio>
     11 #include <algorithm>
     12 using namespace std;
     13 #define l(x) ch[x][0]
     14 #define r(x) ch[x][1]
     15 #define kd(x) (r(fa[x]) == x)
     16 #define setc(f, c, k)   (ch[fa[c] = f][k] = c)
     17 #define isRoot(x)   (r(fa[x]) != x && l(fa[x]) != x)
     18 const int N = 150100;
     19  
     20 struct Edge{
     21     int u, v, a, b;
     22     inline void init(){
     23         scanf("%d %d %d %d", &u, &v, &a, &b);
     24     }
     25     inline bool operator <(const Edge &rhs)const{
     26         return a < rhs.a;
     27     }
     28 }e[100100];
     29 int fa[N], ch[N][2], rev[N], val[N], maxp[N], f[50100];
     30 int INF = 0x7f7f7f7f;
     31  
     32 inline void update(int x) {
     33     maxp[x] = x;
     34     if (val[maxp[x]] < val[maxp[l(x)]])  maxp[x] = maxp[l(x)];
     35     if (val[maxp[x]] < val[maxp[r(x)]])  maxp[x] = maxp[r(x)];
     36 }
     37  
     38 inline void push(int x) {
     39     if (rev[x] and x){
     40         rev[x] = 0;
     41         if (l(x))   rev[l(x)] ^= 1, swap(l(l(x)), r(l(x)));
     42         if (r(x))   rev[r(x)] ^= 1, swap(l(r(x)), r(r(x)));
     43     }
     44 }
     45  
     46 inline void pushDown(int x) {
     47     if (! isRoot(x))    pushDown(fa[x]);
     48     push(x);
     49 }
     50  
     51 inline void rotate(int x) {
     52     int y = fa[x], t = kd(x);
     53     setc(y, ch[x][t^1], t);
     54     if (isRoot(y)) fa[x] = fa[y];
     55     else setc(fa[y], x, kd(y));
     56     setc(x, y, t^1);
     57     update(y); update(x);
     58 }
     59  
     60 inline void splay(int x){
     61     pushDown(x);
     62     while(! isRoot(x)){
     63         if (! isRoot(fa[x]))
     64             if (kd(x) == kd(fa[x]))     rotate(fa[x]);
     65             else    rotate(x); rotate(x);
     66     }
     67 }
     68  
     69 inline void access(int x){
     70     int t = 0;
     71     while(x) {
     72         splay(x); 
     73         r(x) = t; update(x);
     74         t = x; x = fa[x];
     75     }
     76 }
     77  
     78 inline void makeRoot(int x){
     79     access(x); splay(x);
     80     rev[x] ^= 1;  swap(l(x), r(x));
     81 } 
     82  
     83 inline void link(int u, int v) {    makeRoot(u);  fa[u] = v; }
     84  
     85 inline void cut(int u, int v){
     86     makeRoot(u); 
     87     access(v); splay(v);
     88     fa[u] = l(v) = 0;
     89 }
     90  
     91 inline int query(int u, int v){
     92     makeRoot(u);
     93     access(v); splay(v);
     94     return maxp[v];
     95 }
     96  
     97 int find(int x) { return f[x] == x ? x : f[x] = find(f[x]); }
     98  
     99 int main(){
    100     int n, m;
    101     scanf("%d %d", &n, &m);
    102     int ans = INF;
    103     for (int i = 1; i <= m; i++) e[i].init();
    104     for (int i = 1; i <= n; i++) f[i] = i;
    105     sort(e + 1, e + m + 1); 
    106     for (int i = 1; i <= m; i++){
    107         int u = e[i].u, v = e[i].v, rt1 = find(u), rt2 = find(v);
    108         val[i + n] = e[i].b; maxp[i + n] = i + n; 
    109         if (rt1 == rt2){
    110             int p = query(u, v);
    111             if (val[p] > e[i].b)   cut(u, p), cut(v, p);
    112             else   continue;    
    113         }
    114         else f[rt1] = rt2;
    115         link(u, i + n); link(v, i + n);
    116         if (find(1) == find(n)) ans = min(ans, val[query(1, n)] + e[i].a);
    117     }
    118     printf("%d
    ", ans == INF ? -1 : ans);
    119     return 0;
    120 } 
  • 相关阅读:
    Android开源日志框架xlog
    [CrackMe]160个CrackMe之18
    SEH异常
    全局句柄表
    用户层异常的派发与处理
    用户层异常的处理
    内核层异常的收集与处理
    两种异常(CPU异常、用户模拟异常)的收集
    无处不在的页异常
    AppBoxFuture(四). 随需而变-Online Schema Change
  • 原文地址:https://www.cnblogs.com/cminus/p/7056303.html
Copyright © 2011-2022 走看看