zoukankan      html  css  js  c++  java
  • HDU 4297 One and One Story (LCA>RMQ)

    题意就是找森林里的LCA,构图完成了这个题基本就没问题了。

    已知的是所给的图上是可能有环的。那么可以对这些环进行类似缩点的操作(当然不是tarjan),设一个虚拟根0点,链接环上的每一个点。

    对于不在环上的点直接加无向边建树就行。

    预处理出每个环包含哪些点,每个环中点的顺序(环是有方向的)

    对得到的树进行LCA到RMQ的转化,同时记录当前点到0点的距离,O(nlogn)的时间预处理,O(1)的时间求LCA。

    分几种情况:

    1、两点的LCA是环上的同一个点,这个直接出结果(根据距离)

    2、两点的LCA在同一个环的不同点上,这个要根据环的方向判断一下优弧劣弧。

    3、两点的LCA不再同一环上。直接输出-1 -1;

    详见代码吧。。。很搓很搓的写了6K+。。。经此一役,DSU, RMQ,LAC的模板都有了。。。

    View Code
      1 //#pragma comment(linker,"/STACK:1024000000,1024000000")
      2 #include <iostream>
      3 #include <cstdio>
      4 #include <cmath>
      5 #include <vector>
      6 #include <cstring>
      7 #include <algorithm>
      8 #include <string>
      9 #include <set>
     10 #include <functional>
     11 #include <numeric>
     12 #include <sstream>
     13 #include <stack>
     14 
     15 #define CL(arr, val)    memset(arr, val, sizeof(arr))
     16 #define REP(i, n)       for((i) = 0; (i) < (n); ++(i))
     17 #define FOR(i, l, h)    for((i) = (l); (i) <= (h); ++(i))
     18 #define FORD(i, h, l)   for((i) = (h); (i) >= (l); --(i))
     19 #define L(x)    (x) << 1
     20 #define R(x)    (x) << 1 | 1
     21 #define MID(l, r)   (l + r) >> 1
     22 #define Min(x, y)   x < y ? x : y
     23 #define Max(x, y)   x < y ? y : x
     24 #define E(x)    (1 << (x))
     25 #define iabs(x) (x) < 0 ? -(x) : (x)
     26 #define OUT(x)  printf("%I64d\n", x)
     27 #define lowbit(x)   (x)&(-x)
     28 #define Read()    freopen("data.in", "r", stdin)
     29 #define Write()   freopen("data.out", "w", stdout);
     30 
     31 const double eps = 1e-8;
     32 typedef long long LL;
     33 const int inf = ~0u>>2;
     34 
     35 using namespace std;
     36 
     37 const int N = 500010;
     38 int n;
     39 
     40 struct node {
     41     int to;
     42     int next;
     43     node() {}
     44 } g[N<<2];
     45 
     46 int head[N], t;
     47 class Graph {    //树。。
     48 public:
     49     void init() {
     50         CL(head, -1); t = 0;
     51     }
     52     void add(int u, int v) {
     53         g[t].to = v; g[t].next = head[u]; head[u] = t++;
     54     }
     55 }G;
     56 
     57 
     58 int parent[N];
     59 class DSU {    //并查集
     60 public:
     61     void init(int n) {
     62         for(int i = 0; i <= n; ++i) parent[i] = i;
     63     }
     64     void union_set(int a, int b) {
     65         parent[a] = b;
     66     }
     67     int find(int x) {
     68         int k, j;
     69         k = x;
     70         while(x != parent[x])   x = parent[x];
     71 
     72         while(k != x) {
     73             j = parent[k];
     74             parent[k] = x;
     75             k = j;
     76         }
     77         return x;
     78     }
     79 }DSU;
     80 
     81 int D[N], E[N<<1], R[N<<1];
     82 int Min[N<<1][20];
     83 
     84 class RMQ {    //RMQ
     85 public:
     86     void build(int n) {
     87         int i, j, m;
     88         for(i = 1; i <= n; ++i) Min[i][0] = i;
     89         m = int(log(double(n))/log(2.0));
     90         FOR(j, 1, m) {
     91             FOR(i, 1, n - (1<<j) + 1) {
     92                 if(D[Min[i][j-1]] < D[Min[i+(1<<(j-1))][j-1]]) {
     93                     Min[i][j] = Min[i][j-1];
     94                 } else {
     95                     Min[i][j] = Min[i+(1<<(j-1))][j-1];
     96                 }
     97 
     98             }
     99         }
    100     }
    101 
    102     int query(int s, int e) {
    103         int k = log(double(e - s + 1))/log(2.0);
    104         if(D[Min[s][k]] < D[Min[e-(1<<k) + 1][k]])   return  Min[s][k];
    105         else    return Min[e-(1<<k) + 1][k];
    106     }
    107 } Q;
    108 
    109 int dis[N], root[N], cir[N];
    110 int nxt[N];
    111 int cnt;
    112 bool vis[N];
    113 
    114 class LCA {    //LCA
    115 public:
    116     void init() {
    117         CL(D, 0); CL(dis, 0);
    118         CL(E, 0); CL(R, 0);
    119         CL(vis, 0); cnt = 0;
    120     }
    121     void dfs(int t, int dep) {
    122         D[++cnt] = dep;
    123         E[cnt] = t;
    124 
    125         if(!vis[t]) {
    126             R[t] = cnt;
    127             vis[t] = true;
    128         }
    129         for(int i = head[t]; i != -1; i = g[i].next) {
    130             if(vis[g[i].to])    continue;
    131 
    132             dis[g[i].to] = dis[t] + 1;
    133             dfs(g[i].to, dep + 1);
    134 
    135             D[++cnt] = dep;
    136             E[cnt] = t;
    137         }
    138     }
    139     /*
    140     void display() {
    141         int i;
    142         for(i = 1; i <= cnt; ++i)
    143             printf("%-3d", i);
    144         cout << endl;
    145         for(i = 1; i <= cnt; ++i)
    146             printf("%-3d", D[i]);
    147         cout << endl;
    148         for(i = 1; i <= cnt; ++i)
    149             printf("%-3d", E[i]);
    150         cout << endl;
    151         for(i = 1; i <= n; ++i) {
    152             printf("%d ", R[i]);
    153         }
    154         cout << endl;
    155     }
    156     */
    157     void solve() {
    158         init();
    159         dfs(0, 0);
    160         Q.build(cnt);
    161     }
    162 
    163     int query(int x, int y) {
    164         x = R[x]; y = R[y];
    165         if(x > y)   swap(x, y);
    166        // printf("%d\n", Q.query(x, y));
    167         return E[Q.query(x, y)];
    168     }
    169 }LCA;
    170 
    171 void rdfs(int u, int r) {    //把非环上点的根节点都处理出来。
    172     root[u] = r;
    173     for(int i = head[u]; i != -1; i = g[i].next) {
    174         if(root[g[i].to] == -1) {
    175             rdfs(g[i].to, r);
    176         }
    177     }
    178 }
    179 
    180 int num;
    181 int pos[N], len[N];    //每个点在环中的位置,每个环的长度
    182 
    183 void deal() {    //预处理环的情况
    184     CL(cir, -1);  CL(pos, -1);
    185     CL(len, 0);
    186 
    187     DSU.init(n);
    188     int i, j, cnt, x, y;
    189     num = 0;
    190     for(i = 1; i <= n; ++i) {
    191         x = DSU.find(i);
    192         y = DSU.find(nxt[i]);
    193         if(x == y)  cir[i] = ++num;
    194         DSU.union_set(x, y);
    195     }
    196 
    197     for(i = 1; i <= n; ++i) {
    198         if(cir[i] != -1) {
    199             j = nxt[i];
    200             cnt = 0;
    201             pos[i] = ++cnt;
    202             root[i] = i;
    203             while(j != i) {
    204                 pos[j] = ++cnt;
    205                 root[j] = j;
    206                 cir[j] = cir[i];
    207                 j = nxt[j];
    208             }
    209             len[cir[i]] = cnt;
    210         }
    211     }
    212 }
    213 
    214 
    215 int main() {
    216     //Read();
    217 
    218     int i, k, p, ra, rb;
    219     int a, b, x1, y1, x2, y2;
    220     int ansx, ansy;
    221     while(~scanf("%d%d", &n, &k)) {
    222         CL(root, -1);
    223         for(i = 1; i <= n; ++i) scanf("%d", nxt + i);
    224         deal();
    225         G.init();
    226         for(i = 1; i <= n; ++i) {
    227             if(root[i] != i) {
    228                 G.add(i, nxt[i]);
    229                 G.add(nxt[i], i);
    230                 //printf("*%d %d\n", i, nxt[i]);
    231             }
    232         }
    233         for(i = 1; i <= n; ++i) {
    234             if(root[i] == i) {
    235                 rdfs(i, i);
    236                 G.add(0, i);
    237                 G.add(i, 0);
    238                 //printf("*%d %d\n", 0, nxt[i]);
    239             }
    240         }
    241         LCA.solve();
    242         //LCA.display();
    243         while(k--) {
    244             scanf("%d%d", &a, &b);
    245             p = LCA.query(a, b);
    246             if(p != 0) {
    247                 printf("%d %d\n", dis[a] - dis[p], dis[b] - dis[p]);
    248                 continue;
    249             }
    250             ra = root[a], rb = root[b];
    251             if(cir[ra] != cir[rb])  {printf("-1 -1\n"); continue;}
    252             x1 = x2 = dis[a] - 1;
    253             y1 = y2 = dis[b] - 1;
    254             //A沿着环的方向靠近B
    255             if(pos[ra] < pos[rb])   x1 += pos[rb] - pos[ra];
    256             else    x1 += len[cir[ra]] - (pos[ra] - pos[rb]);
    257             //B沿着环的方向靠近A
    258             if(pos[rb] < pos[ra])   y2 += pos[ra] - pos[rb];
    259             else    y2 += len[cir[rb]] - (pos[rb] - pos[ra]);
    260             /*
    261             printf("(x1, y1) = (%d, %d)\n", x1, y1);
    262             printf("(x2, y2) = (%d, %d)\n", x2, y2);
    263             */
    264             if(max(x1, y1) < max(x2, y2))   ansx = x1, ansy = y1;
    265             else if(max(x1, y1) > max(x2, y2))  ansx = x2, ansy = y2;
    266             else {
    267                 if(min(x1, y1) < min(x2, y2))   ansx = x1, ansy = y1;
    268                 else    if(min(x1, y1) > min(x2, y2))   ansx = x2, ansy = y2;
    269                 else {
    270                     if(x1 >= y1)    ansx = x1, ansy = y1;
    271                     else    ansx = x2, ansy = y2;
    272                 }
    273             }
    274             printf("%d %d\n", ansx, ansy);
    275         }
    276     }
    277     return 0;
    278 }
  • 相关阅读:
    第k小元素学习记录
    线段树学习笔记
    数论方面的知识积累
    javascript 例子
    数据绑定以及Container.DataItem的具体分析
    C#委托和事件
    C#中的特性(Attributes)(翻译)
    gridview和repeater中取得行的序号
    理解 Ajax 及其工作原理,构建网站的一种有效方法
    JS数组对象参考
  • 原文地址:https://www.cnblogs.com/vongang/p/2695987.html
Copyright © 2011-2022 走看看