zoukankan      html  css  js  c++  java
  • 【HDOJ】4297 One and One Story

    综合性很强的题目。
    存在环,可以用tarjan处理,然后需要求LCA。并查集+RMQ可以搞。
    非常不错的题目。

      1 /* 4297 */
      2 #include <iostream>
      3 #include <sstream>
      4 #include <string>
      5 #include <map>
      6 #include <queue>
      7 #include <set>
      8 #include <stack>
      9 #include <vector>
     10 #include <deque>
     11 #include <algorithm>
     12 #include <cstdio>
     13 #include <cmath>
     14 #include <ctime>
     15 #include <cstring>
     16 #include <climits>
     17 #include <cctype>
     18 #include <cassert>
     19 #include <functional>
     20 #include <iterator>
     21 #include <iomanip>
     22 using namespace std;
     23 //#pragma comment(linker,"/STACK:102400000,1024000")
     24 
     25 #define sti                set<int>
     26 #define stpii            set<pair<int, int> >
     27 #define mpii            map<int,int>
     28 #define vi                vector<int>
     29 #define pii                pair<int,int>
     30 #define vpii            vector<pair<int,int> >
     31 #define rep(i, a, n)     for (int i=a;i<n;++i)
     32 #define per(i, a, n)     for (int i=n-1;i>=a;--i)
     33 #define clr                clear
     34 #define pb                 push_back
     35 #define mp                 make_pair
     36 #define fir                first
     37 #define sec                second
     38 #define all(x)             (x).begin(),(x).end()
     39 #define SZ(x)             ((int)(x).size())
     40 #define lson            l, mid, rt<<1
     41 #define rson            mid+1, r, rt<<1|1
     42 
     43 typedef struct {
     44     int v, nxt;
     45 } edge_t;
     46 
     47 const int maxn = 500005;
     48 // input
     49 int link[maxn], link2[maxn];
     50 
     51 // tarjan
     52 int low[maxn], pre[maxn], bn[maxn], C[maxn];
     53 int S[maxn], top;
     54 int dfs_clock, block;
     55 
     56 // LCA
     57 int head[maxn], l;
     58 edge_t E[maxn<<1];
     59 int deg[maxn], beg[maxn];
     60 int deep[maxn], V[maxn<<1], D[maxn<<1];
     61 
     62 // RMQ
     63 int dp[maxn<<1][20];
     64 
     65 int dis[maxn];
     66 int fa[maxn];
     67 int n;
     68 
     69 
     70 int find(int x) {
     71     if (x == fa[x])
     72         return x;
     73     
     74     int tmp = fa[x];
     75     fa[x] = find(fa[x]);
     76     dis[x] += dis[tmp];
     77     return fa[x];
     78 }
     79 
     80 void tarjan(int u) {
     81     S[top++] = u;
     82     pre[u] = low[u] = ++dfs_clock;
     83     
     84     int v = link[u];
     85     
     86     if (!pre[v]) {
     87         tarjan(v);
     88         low[u] = min(low[u], low[v]);
     89     } else if (!bn[v]) {
     90         low[u] = min(low[u], pre[v]);
     91     }
     92     
     93     if (pre[u] == low[u]) {
     94         ++block;
     95         C[block] = 0;
     96         do {
     97             bn[S[--top]] = block;
     98             ++C[block];
     99         } while (S[top] != u);
    100     }
    101 }
    102 
    103 void addEdge(int u, int v) {
    104     E[l].v = v;
    105     E[l].nxt = head[u];
    106     head[u] = l++;
    107 }
    108 
    109 void dfs(int u, int d) {
    110     deep[u] = d;
    111     V[++top] = u;
    112     D[top] = d;
    113     beg[u] = top;
    114     
    115     int v, k;
    116     
    117     for (k=head[u]; k!=-1; k=E[k].nxt) {
    118         v = E[k].v;
    119         if (link2[v] == -1) {
    120             link2[v] = link2[u];
    121         }
    122         dfs(v, d+1);
    123         V[++top] = u;
    124         D[top] = d;
    125     }
    126 }
    127 
    128 void RMQ_init() {
    129     int len = top;
    130     int i, j, k;
    131     
    132     for (i=1; i<=len; ++i)
    133         dp[i][0] = i;
    134     for (j=1; (1<<j)<=len; ++j) {
    135         for (i=1; i+(1<<j)-1<=len; ++i) {
    136             if (D[dp[i][j-1]] < D[dp[i+(1<<(j-1))][j-1]])
    137                 dp[i][j] = dp[i][j-1];
    138             else
    139                 dp[i][j] = dp[i+(1<<(j-1))][j-1];
    140         }
    141     }
    142 }
    143 
    144 int RMQ(int l, int r) {
    145     if (l > r)
    146         swap(l, r);
    147     
    148     int k = 0;
    149     
    150     while ((1<<(k+1)) <= r-l+1)
    151         ++k;
    152     
    153     if (D[dp[l][k]] < D[dp[r-(1<<k)+1][k]])
    154         return V[dp[l][k]];
    155     else
    156         return V[dp[r-(1<<k)+1][k]];
    157 }
    158 
    159 void init() {
    160     dfs_clock = top = block = 0;
    161     memset(pre, 0, sizeof(pre));
    162     memset(bn, 0, sizeof(bn));
    163     
    164     rep(i, 1, n+1) {
    165         if (!pre[i])
    166             tarjan(i);
    167     }
    168     
    169     l = 0;
    170     memset(head, -1, sizeof(head));
    171     memset(link2, -1, sizeof(link2));
    172     memset(deg, 0, sizeof(deg));
    173     memset(dis, 0, sizeof(dis));
    174     rep(i, 1, n+1) {
    175         int bv = bn[i];
    176         int bu = bn[link[i]];
    177         if (bu == bv) {
    178             int fx = find(link[i]);
    179             int fy = find(i);
    180             if (fx != fy) {
    181                 fa[fy] = fx;
    182                 dis[fy] = dis[link[i]] + 1;
    183             }
    184         } else {
    185             addEdge(bu, bv);
    186             ++deg[bv];
    187             if (C[bu] > 1) {
    188                 link2[bv] = link[i];
    189             }
    190         }
    191     }
    192     
    193     rep(i, 1, block+1) {
    194         if (deg[i] == 0)
    195             addEdge(0, i);
    196     }
    197     
    198     
    199     // init RMQ
    200     top = 0;
    201     dfs(0, 0);
    202     RMQ_init();
    203 }
    204 
    205 void solve(int u, int v) {
    206     if (u == v) {
    207         puts("0 0");
    208         return ;
    209     }
    210     
    211     int bu = bn[u];
    212     int bv = bn[v];
    213     int lca = RMQ(beg[bu], beg[bv]);
    214     
    215     
    216     #ifndef ONLINE_JUDGE
    217         printf("bu = %d, bv = %d, lca = %d
    ", bu, bv, lca);
    218     #endif
    219     
    220     if (lca == 0) {
    221         puts("-1 -1");
    222         return ;
    223     }
    224     
    225     if (C[lca] == 1) {
    226         printf("%d %d
    ", deep[bu]-deep[lca], deep[bv]-deep[lca]);
    227         return ;
    228     }
    229     
    230     int u2v, v2u;
    231     int du, dv;
    232     
    233     if (bu == bv) {
    234         du = dv = 0;
    235         find(u);
    236         find(v);
    237         
    238         if (dis[u] < dis[v]) {
    239             u2v = C[bu] + dis[u] - dis[v];
    240             v2u = dis[v] - dis[u];
    241         } else {
    242             u2v = dis[u] - dis[v];
    243             v2u = C[bv] + dis[v] - dis[u];
    244         }
    245         
    246     } else {
    247         
    248         du = deep[bu] - deep[lca];
    249         dv = deep[bv] - deep[lca];
    250         
    251         int uu = link2[bu]==-1 ? u:link2[bu];
    252         int vv = link2[bv]==-1 ? v:link2[bv];
    253         
    254         find(uu);
    255         find(vv);
    256         
    257         #ifndef ONLINE_JUDGE
    258             // printf("uu=%d, duu=%d, vv=%d, dvv=%d
    ", uu, dis[uu], vv, dis[vv]);
    259         #endif
    260         if (dis[uu] < dis[vv]) {
    261             u2v = C[lca] + dis[uu] - dis[vv];
    262             v2u = dis[vv] - dis[uu];
    263         } else {
    264             u2v = dis[uu] - dis[vv];
    265             v2u = C[lca] + dis[vv] - dis[uu];
    266         }
    267     }
    268     
    269     #ifndef ONLINE_JUDGE
    270         printf("du=%d, dv=%d, u2v=%d, v2u=%d
    ", du,dv,u2v,v2u);
    271     #endif
    272     if (max(u2v+du, dv) < max(v2u+dv, du)) {
    273         printf("%d %d
    ", u2v+du, dv);
    274     } else if (max(u2v+du, dv) > max(v2u+dv, du)) {
    275         printf("%d %d
    ", du, v2u+dv);
    276     } else {
    277         if (min(u2v+du, dv) < min(v2u+dv, du)) {
    278             printf("%d %d
    ", u2v+du, dv);
    279         } else if (min(u2v+du, dv) > min(v2u+dv, du)) {
    280             printf("%d %d
    ", du, v2u+dv);
    281         } else {
    282             printf("%d %d
    ", max(u2v+du, dv), min(u2v+du, dv));
    283         }
    284     }
    285 }
    286 
    287 int main() {
    288     ios::sync_with_stdio(false);
    289     #ifndef ONLINE_JUDGE
    290         freopen("data.in", "r", stdin);
    291         freopen("data.out", "w", stdout);
    292     #endif
    293     
    294     int q;
    295     int u, v;
    296     
    297     while (scanf("%d %d", &n, &q)!=EOF) {
    298         rep(i, 1, n+1) {
    299             fa[i] = i;
    300             scanf("%d", &link[i]);
    301         }
    302         init();
    303         while (q--) {
    304             scanf("%d %d", &u, &v);
    305             solve(u, v);
    306         }
    307     }
    308     
    309     #ifndef ONLINE_JUDGE
    310         printf("time = %d.
    ", (int)clock());
    311     #endif
    312     
    313     return 0;
    314 }

     数据生成器。

     1 from random import randint, shuffle
     2 import shutil
     3 import string
     4 
     5 
     6 def GenDataIn():
     7     with open("data.in", "w") as fout:
     8         t = 10
     9         bound = 5*10**5
    10         for tt in xrange(t):
    11             n = randint(bound/10, bound)
    12             q = randint(bound/10, bound)
    13             fout.write("%d %d
    " % (n, q))
    14             dataList = []
    15             for i in xrange(n):
    16                 x = randint(1, n)
    17                 dataList.append(x)
    18             fout.write(" ".join(map(str, dataList)) + "
    ")
    19             for i in xrange(q):
    20                 u = randint(1, n)
    21                 v = randint(1, n)
    22                 fout.write("%d %d
    " % (u, v))
    23                 
    24 def MovDataIn():
    25     desFileName = "F:eclipse_prjworkspacehdojdata.in"
    26     shutil.copyfile("data.in", desFileName)
    27 
    28     
    29 if __name__ == "__main__":
    30     GenDataIn()
    31     MovDataIn()
  • 相关阅读:
    选择 冒泡 快速 插入排序
    类方法
    Java--静态区域块
    打印字母如何显示声调
    navicat 创建的表,username字段不能接受中文名字。
    C++primer plus第六版课后编程题答案10.8(来个高手教教我)
    C++primer plus第六版课后编程题答案10.7
    C++primer plus第六版课后编程题答案10.6
    错误 1 error C2143: 语法错误 : 缺少“;”(在“using”的前面)
    C++primer plus第六版课后编程题答案10.5
  • 原文地址:https://www.cnblogs.com/bombe1013/p/5171347.html
Copyright © 2011-2022 走看看