• [NOI2018]归程 kruskal重构树


    ~~~题面~~~

    题解:

      此题可以用可持久化并查集暴力水过,但正解是kruskal重构树。

      不会kruskal重构树请戳:kruskal重构树

      观察到车可以通过哪些边跟边的长度并没有关系,所以考虑用边的海拔排序建出重构树,这样我们就得到了一个只跟海拔相关的关系。

      于是对于任意水位线,我们都可以得知,在不超过这个水位线的情况下我们可以到达哪些点,也就是哪些点可以使用车子到达,既然我们已经可以知道这个东西了,显然我们只需要在这些点中找到使得步行距离最短的点即可。

      因为要使得步行路径最短,所以要先预处理出每个点到1的最短路,然后每个点的点权就是它到1号节点的最短路了,然后每次查询的时候,不断倍增向上跳,直到水位线超过海拔就停下,因为重构树的特性,所有可以到达的节点都会在你当前停下的这个点下面(属于这个点的子树),

      因此我们找到了这个停下的节点,就已经知道我们可以到达哪些点了,这个时候我们要做的就是查询这个节点管理的叶子节点内权值最小的那个,这个可以在预处理倍增数组的时候用树形DP求出来,每个节点的点权即当前节点子树内的权值最小值。

      于是对于每次查询,我们只需要倍增找到对应的停下节点,然后查询这个节点的点权即可。

      1 #include<bits/stdc++.h>
      2 using namespace std;
      3 #define R register int
      4 #define AC 300100
      5 #define ac 800100
      6 
      7 int n, m, cnt;
      8 int s[AC * 2], g[AC * 2], belong[AC * 2], dis[AC];
      9 int f[AC * 2][23];
     10 int Head[AC * 2], Next[ac], date[ac], len[ac], tot;
     11 int Head2[AC * 2], Next2[ac], date2[ac], tot2;
     12 bool vis[AC];
     13 
     14 struct road{
     15     int x, y, high;
     16 }way[ac];
     17 
     18 struct node{
     19     int x, dis;
     20 };
     21 
     22 struct cmp{
     23     bool operator () (node a, node b)
     24     {
     25         return a.dis > b.dis;
     26     }
     27 };
     28 
     29 priority_queue<node, vector<node>, cmp> q;
     30 
     31 inline int read()
     32 {
     33     int x = 0;char c = getchar();
     34     while(c > '9' || c < '0') c = getchar();
     35     while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
     36     return x;
     37 }
     38 
     39 inline void add(int f, int w, int S)
     40 {
     41     date[++tot] = w, Next[tot] = Head[f], Head[f] = tot, len[tot] = S;
     42     date[++tot] = f, Next[tot] = Head[w], Head[w] = tot, len[tot] = S;
     43 }
     44 
     45 inline int Min(int a, int b)
     46 {
     47     if(a < b) return a;
     48     else return b;
     49 }
     50 
     51 inline void upmin(int &a, int b)
     52 {
     53     if(b < a) a = b;
     54 }
     55 
     56 inline bool cmp1(road a, road b)
     57 {
     58     return a.high > b.high;
     59 }
     60 
     61 #define date date2
     62 #define Next Next2
     63 #define tot tot2
     64 #define Head Head2
     65 
     66 inline void add2(int f, int w)
     67 {
     68     date[++tot] = w, Next[tot] = Head[f], Head[f] = tot, belong[w] = f;
     69 }
     70 
     71 void dfs(int x)
     72 {
     73     int now;
     74     g[x] = INT_MAX;
     75     for(R i = 1; i <= 22; i ++)
     76         f[x][i] = f[f[x][i - 1]][i - 1];
     77     if(x <= n) g[x] = dis[x];
     78     for(R i = Head[x]; i; i = Next[i])
     79     {
     80         now = date[i];
     81         //if(f[x][0] == now) continue;
     82         f[now][0] = x;
     83         dfs(now);
     84         upmin(g[x], g[now]);
     85     }
     86 }
     87 
     88 #undef date
     89 #undef Next
     90 #undef tot
     91 #undef Head
     92 
     93 void init()
     94 {
     95     memset(Head, 0, sizeof(Head));
     96     memset(Head2, 0, sizeof(Head2));
     97     memset(dis, 127, sizeof(dis));
     98     //memset(g, 127, sizeof(g));
     99     memset(vis, 0, sizeof(vis));
    100     tot = tot2 = 0;
    101     //memset(f, 0, sizeof(f));
    102 }
    103 
    104 void pre()
    105 {
    106     n = cnt = read(), m = read();
    107     for(R i = 1; i <= m; i ++)
    108     {
    109         int a = read(), b = read(), c = read(), d = read();
    110         way[i] = (road){a, b, d};
    111         add(a, b, c);
    112     }
    113     sort(way + 1, way + m + 1, cmp1);
    114 }
    115 
    116 void dij()
    117 {
    118     node x; int now;
    119     dis[1] = 0, q.push((node){1, 0});
    120     while(!q.empty())
    121     {
    122         x = q.top(), q.pop();
    123         while(vis[x.x] && !q.empty()) x = q.top(), q.pop();
    124         vis[x.x] = true;
    125         for(R i = Head[x.x]; i; i = Next[i])
    126         {
    127             now = date[i];
    128             if(dis[now] > dis[x.x] + len[i])
    129             {
    130                 dis[now] = dis[x.x] + len[i];
    131                 q.push((node){now, dis[now]});
    132             }
    133         }
    134     }
    135 }
    136 
    137 int find(int x)
    138 {
    139     if(belong[x] == x) return x;
    140     else return belong[x] = find(belong[x]);
    141 }
    142 
    143 void build()
    144 {
    145     int b = n + n;
    146     for(R i = 1; i <= b; i ++) belong[i] = i;
    147     for(R i = 1; i <= m; i ++)
    148     {
    149         int fx = find(way[i].x), fy = find(way[i].y);
    150         if(fx == fy) continue;
    151         s[++cnt] = way[i].high;
    152         add2(cnt, fx), add2(cnt, fy);
    153     }
    154     for(R i = 0; i <= 22; i ++) f[cnt][i] = 0;
    155 }
    156 
    157 int jump(int x, int d)
    158 {
    159     for(R i = 22; i >= 0; i--)
    160         if(s[f[x][i]] > d) x = f[x][i];
    161     return g[x];
    162 }
    163 
    164 void work()
    165 {
    166     int now = 0, all = read(), k = read(), tt = read();
    167     for(R i = 1; i <= all; i ++)
    168     {
    169         int a = read(), b = read();
    170         a = (a + k * now - 1) % n + 1;
    171         b = (b + k * now) % (tt + 1);
    172         printf("%d
    ", now = jump(a, b));
    173     }
    174 }
    175 
    176 int main()
    177 {
    178     freopen("10.in", "r", stdin);
    179     int T = read();
    180     while(T --)
    181     {
    182         init();//初始化
    183         pre();//读入
    184         build();//重构树
    185         dij();//最短路
    186         dfs(cnt);//树上倍增
    187         work();//回答询问
    188     }
    189     fclose(stdin);
    190     return 0;
    191 }
    View Code
  • 相关阅读:
    AD设计过程中的注意事项
    ds18b20再硬件设计部分的注意事项
    时序设计的注意事项
    【HackerRank】 Game Of Thrones
    【HackerRank】Halloween party
    【HackerRank】The Love-Letter Mystery
    【HackerRank】Gem Stones
    【HackerRank】Service Lane
    【HackerRank】Utopian tree
    【leetcode刷题笔记】Word Ladder II
  • 原文地址:https://www.cnblogs.com/ww3113306/p/9710505.html
Copyright © 2020-2023  润新知