【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\n", 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\n", 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\n", 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\n", du,dv,u2v,v2u); 271 #endif 272 if (max(u2v+du, dv) < max(v2u+dv, du)) { 273 printf("%d %d\n", u2v+du, dv); 274 } else if (max(u2v+du, dv) > max(v2u+dv, du)) { 275 printf("%d %d\n", du, v2u+dv); 276 } else { 277 if (min(u2v+du, dv) < min(v2u+dv, du)) { 278 printf("%d %d\n", u2v+du, dv); 279 } else if (min(u2v+du, dv) > min(v2u+dv, du)) { 280 printf("%d %d\n", du, v2u+dv); 281 } else { 282 printf("%d %d\n", 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.\n", (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" % (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)) + "\n") 19 for i in xrange(q): 20 u = randint(1, n) 21 v = randint(1, n) 22 fout.write("%d %d\n" % (u, v)) 23 24 def MovDataIn(): 25 desFileName = "F:\eclipse_prj\workspace\hdoj\data.in" 26 shutil.copyfile("data.in", desFileName) 27 28 29 if __name__ == "__main__": 30 GenDataIn() 31 MovDataIn()