zoukankan      html  css  js  c++  java
  • [NOI2018]归程

    今年D1T1,平心而论,如果能想到kruskal重构树还是很简单的。

    ......苟屁啊!虽然跟其他的比是简单些,但是思维难度中上,代码难度中上,怎么看都很符合NOI T1啊。

    本题还有可持久化并查集的做法,以高度为版本。我没有打......

    言归正传,来看题。

    给你一个无向图,每条边有高度和长度。每次询问,从点s出发,只能经过高度大于h的边所能到达的点中,距1号点最近的点的距离。强制在线。

    n<=200000,m<=400000,q<=400000

    首先,离线有65分,十分可观。我们把边和询问都按照高度排序。然后依次加入,并查集维护连通块内dis最小值。

    克鲁斯卡尔重构树解法:

    首先讲什么是克鲁斯卡尔重构树:说起来也蛮简单,就是你把边排序,加边的时候如果连通就不加,否则新建节点代表这个连通块,边的两端所在连通块的代表节点作为这个新节点的两个子节点。

    这样你要查询高度h时dis min,只需维护一个节点所代表连通块内dis最小值即可。每次向上跳,可以发现一条链上的dis min单调不增。然后就倍增了,类似lca。

    啊我到底在口胡什么。

      1 #include <cstdio>
      2 #include <algorithm>
      3 #include <cstring>
      4 #include <queue>
      5 
      6 const int N = 200010, INF = 0x7f7f7f7f;
      7 
      8 struct Edge_1 {
      9     int v, len, nex;
     10 }edge_1[N << 2]; int top_1; // for dijkstra
     11 
     12 struct POI {
     13     int id, dis;
     14     inline bool operator <(const POI &d) const {
     15         return dis > d.dis;
     16     }
     17     POI(int a, int b) {
     18         id = a;
     19         dis = b;
     20     }
     21 }; // for dijkstra
     22 
     23 struct Edge_2 {
     24     int u, v, h;
     25     inline bool operator <(const Edge_2 &d) const {
     26         return h > d.h;
     27     }
     28 }edge_2[N << 1]; int top_2; // for sort kruskal
     29 
     30 struct UFS {
     31     int fa[N * 3];
     32     inline void clear() {
     33         for(int i = 1; i < N * 3; i++) {
     34             fa[i] = i;
     35         }
     36         return;
     37     }
     38     UFS() {
     39         clear();
     40     }
     41     int find(int x) {
     42         if(fa[x] == x) {
     43             return x;
     44         }
     45         return fa[x] = find(fa[x]);
     46     }
     47     inline void merge(int x, int y) { // x <- y
     48         fa[find(y)] = find(x);
     49         return;
     50     }
     51 }ufs;
     52 
     53 int e[N], dis[N * 3]; // for dijkstra
     54 int fa[N * 3][21], tot, h[N * 3]; // for kruskal
     55 
     56 inline void add_1(int x, int y, int z) {
     57     top_1++;
     58     edge_1[top_1].v = y;
     59     edge_1[top_1].len = z;
     60     edge_1[top_1].nex = e[x];
     61     e[x] = top_1;
     62     return;
     63 }
     64 
     65 inline void add_2(int x, int y, int z) {
     66     top_2++;
     67     edge_2[top_2].u = x;
     68     edge_2[top_2].v = y;
     69     edge_2[top_2].h = z;
     70     return;
     71 }
     72 
     73 inline void clear() {
     74     top_1 = 0;
     75     top_2 = 0;
     76     memset(e, 0, sizeof(e));
     77     ufs.clear();
     78     return;
     79 }
     80 
     81 inline void dijkstra() {
     82     std::priority_queue<POI> Q;
     83     memset(dis, 0x3f, sizeof(dis));
     84     dis[1] = 0;
     85     Q.push(POI(1, 0)); // POI(id, dis)
     86     while(!Q.empty()) {
     87         while(!Q.empty() && dis[Q.top().id] != Q.top().dis) {
     88             Q.pop();
     89         }
     90         if(Q.empty()) {
     91             break;
     92         }
     93         int x = Q.top().id;
     94         Q.pop();
     95         for(int i = e[x]; i; i = edge_1[i].nex) {
     96             int y = edge_1[i].v;
     97             if(dis[y] > dis[x] + edge_1[i].len) {
     98                 dis[y] = dis[x] + edge_1[i].len;
     99                 Q.push(POI(y, dis[y]));
    100             }
    101         }
    102     }
    103     return;
    104 }
    105 
    106 inline void add(int p) {
    107     int x = ufs.find(edge_2[p].u);
    108     int y = ufs.find(edge_2[p].v);
    109     if(x == y) {
    110         return;
    111     }
    112     ++tot;
    113     fa[x][0] = tot;
    114     fa[y][0] = tot;
    115     ufs.merge(tot, x);
    116     ufs.merge(tot, y);
    117     h[tot] = edge_2[p].h;
    118     dis[tot] = std::min(dis[x], dis[y]);
    119     return;
    120 }
    121 
    122 inline int solve(int x, int high) {
    123     int t = 20;
    124     while(t >= 0) {
    125         if(h[fa[x][t]] > high) {
    126             x = fa[x][t];
    127         }
    128         t--;
    129     }
    130     return dis[x];
    131 }
    132 
    133 int main() {
    134     int T;
    135     scanf("%d", &T);
    136     while(T--) {
    137         int n, m;
    138         scanf("%d%d", &n, &m);
    139         tot = n;
    140         h[0] = -1;
    141         for(int i = 1, x, y, z, w; i <= m; i++) {
    142             scanf("%d%d%d%d", &x, &y, &z, &w);
    143             add_1(x, y, z);
    144             add_1(y, x, z);
    145             add_2(x, y, w);
    146         }
    147 
    148         // prework
    149         dijkstra();
    150         std::sort(edge_2 + 1, edge_2 + m + 1);
    151         for(int i = 1; i <= m; i++) {
    152             add(i);
    153         }
    154         for(int i = 1; i <= 20; i++) {
    155             for(int x = 1; x <= tot; x++) {
    156                 fa[x][i] = fa[fa[x][i - 1]][i - 1];
    157             }
    158         }
    159 
    160         int q, k, s, op, high, la = 0;
    161         scanf("%d%d%d", &q, &k, &s);
    162         while(q--) {
    163             scanf("%d%d", &op, &high);
    164             op = (op + k * la - 1) % n + 1;
    165             high = (high + k * la) % (s + 1);
    166             la = solve(op, high);
    167             printf("%d
    ", la);
    168         }
    169         clear();
    170     }
    171     return 0;
    172 }
    AC代码

    170行代码还行。

  • 相关阅读:
    在web项目启动时,使用监听器来执行某个方法
    spring boot --- 初级体验
    Java字符串连接最佳实践
    JPA
    基于Spring AOP的JDK动态代理和CGLIB代理
    jQuery.validate表单校验+bootstrap
    搜索技术---solr
    最常用的缓存技术---redis入门
    内外网同时访问的路由配置
    创建 Visual Studio 2017 离线安装
  • 原文地址:https://www.cnblogs.com/huyufeifei/p/9737738.html
Copyright © 2011-2022 走看看