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行代码还行。

  • 相关阅读:
    UVA12125 March of the Penguins (最大流+拆点)
    UVA 1317 Concert Hall Scheduling(最小费用最大流)
    UVA10249 The Grand Dinner(最大流)
    UVA1349 Optimal Bus Route Design(KM最佳完美匹配)
    UVA1212 Duopoly(最大流最小割)
    UVA1395 Slim Span(kruskal)
    UVA1045 The Great Wall Game(二分图最佳匹配)
    UVA12168 Cat vs. Dog( 二分图最大独立集)
    hdu3488Tour(KM最佳完美匹配)
    UVA1345 Jamie's Contact Groups(最大流+二分)
  • 原文地址:https://www.cnblogs.com/huyufeifei/p/9737738.html
Copyright © 2011-2022 走看看