zoukankan      html  css  js  c++  java
  • LOJ #2718. 「NOI2018」归程

    #2718. 「NOI2018」归程

    https://loj.ac/problem/2718

    分析:

      首先按h建立kruskal重构树,每个节点保存新加入这条边的高度。另记录一个数组dis,表示在重构树中,以这个点为根的子树中,距离1号点最小的距离是多少。

      查询所有大于某个值得边,就是在kruskal重构树,从下往上找到第一个大于这个值的点。然后这个点的dis就是答案。

    代码:

      1 #include<bits/stdc++.h>
      2 using namespace std;
      3 typedef long long LL;
      4 
      5 inline int read() { 
      6     int x=0,f=1;char ch=getchar();for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-1;
      7     for(;isdigit(ch);ch=getchar())x=x*10+ch-'0';return x*f;
      8 }
      9 
     10 const int N = 200100;
     11 const int M = 400100;
     12 const LL Linf = 1e18;
     13 const int inf = 1e9;
     14 
     15 int n, m, CntNode, TOT, Enum;
     16 
     17 struct Heap{
     18     int u; LL w;
     19     Heap() {}
     20     Heap(int a,LL b) {u = a, w = b;}
     21     bool operator < (const Heap &A) const {
     22         return w > A.w; // 小根堆 
     23     }
     24 };
     25 int head[N<<1], nxt[M<<1], to[M<<1];
     26 LL len[M<<1], dis[N<<1]; // dis开两倍空间,下面会用到 
     27 bool vis[N];
     28 priority_queue<Heap>q;
     29 
     30 void Dijkstra(int S) {
     31     for (int i=1; i<=n; ++i) 
     32         dis[i] = Linf, vis[i] = false;
     33     dis[S] = 0;
     34     q.push(Heap(S,0));
     35     while (!q.empty()) {
     36         int u = q.top().u; q.pop();
     37         if (vis[u]) continue;
     38         vis[u] = true;
     39         for (int i=head[u]; i; i=nxt[i]) {
     40             int v = to[i];
     41             if (dis[v] > dis[u] + len[i]) {
     42                 dis[v] = dis[u] + len[i];
     43                 q.push(Heap(v,dis[v]));
     44             }
     45         }
     46     }
     47 }
     48 
     49 struct Edge{
     50     int u, v, h;
     51     bool operator < (const Edge &A) const {
     52         return h > A.h;
     53     }
     54 }e[M];
     55 int val[N<<1], fa[N<<1], f[N<<1][21];
     56 
     57 int find(int x) {
     58     return x == fa[x] ? x : fa[x] = find(fa[x]);
     59 }
     60 void Kruskal() {
     61     sort(e+1, e+m+1);
     62     for (int i=1; i<=n+n; ++i) fa[i] = i;
     63     int Count_Edge = 0;
     64     for (int i=1; i<=m; ++i) {
     65         int u = find(e[i].u), v = find(e[i].v);
     66         if (u == v) continue;
     67         val[++CntNode] = e[i].h;
     68         fa[u] = fa[v] = CntNode;
     69         f[u][0] = CntNode, f[v][0] = CntNode;
     70         dis[CntNode] = min(dis[v], dis[u]);
     71         if ((++Count_Edge) == n - 1) break;
     72     }
     73 }
     74 
     75 void add_edge(int u,int v,int w,int h) {
     76     ++Enum; to[Enum] = v; len[Enum] = w; nxt[Enum] = head[u]; head[u] = Enum;
     77     ++Enum; to[Enum] = u; len[Enum] = w; nxt[Enum] = head[v]; head[v] = Enum;
     78     ++TOT; e[TOT].u = u; e[TOT].v = v; e[TOT].h = h;
     79 }
     80 void init() {
     81     TOT = Enum = n = m = CntNode = 0;
     82     memset(head, 0, sizeof(head));
     83     memset(f, 0, sizeof(f));
     84 }
     85 void solve() {
     86     init();
     87     n = read(),m = read(),CntNode = n;
     88     for (int i=1; i<=m; ++i) {
     89         int u = read(), v = read(), w = read(), h = read();
     90         add_edge(u, v, w, h);
     91     }
     92     Dijkstra(1);
     93     Kruskal();
     94     for (int j=1; j<=20; ++j) 
     95         for (int i=1; i<=CntNode; ++i) 
     96             f[i][j] = f[f[i][j-1]][j-1];
     97     
     98     LL Q = read(), K = read(), S = read();
     99     LL last = 0;
    100     while (Q--) {
    101         int v = read(), p = read();
    102         v = (v + K * last - 1) % n + 1;
    103         p = (p + K * last) % (S + 1); //--
    104         for (int j=20; j>=0; --j) 
    105             if (f[v][j] && val[f[v][j]] > p) v = f[v][j];
    106         
    107         printf("%lld
    ",last=dis[v]);
    108     }
    109 }
    110 
    111 int main () {
    112     freopen("return.in","r",stdin);
    113     freopen("return.out","w",stdout);
    114     int Case = read();
    115     while (Case --) solve();    
    116     return 0;
    117 }
  • 相关阅读:
    mysql数据索引
    JQuery学习
    (原创)JAVA多线程一传统多线程
    JAVA常用的XML解析方法
    java集合比较
    Hibernate总结3
    Hibernate总结4之HQL
    HDU5716, HDU5745【dp+bitset】
    Can of Worms 【迭代/线段树】
    CSU 1802 小X的战斗力【拓扑dp】
  • 原文地址:https://www.cnblogs.com/mjtcn/p/9354050.html
Copyright © 2011-2022 走看看