牛客多校8 J-Tree
阿新 • • 發佈:2021-08-10
原題連結
樹上兩點之間的路徑是唯一的,我們發現,當有人脫離了兩者之間的路徑時,他所走的步數不會被對方所幹預(雙方已經毫無關係了),故可以對抗搜尋,當有一方離開兩點路徑之時,直接統計答案。
詳情見程式碼:
/* 牛客多校8-J 對抗搜尋,剪枝,rmq表預處理。 思路: dfs1預處理出s到t 的唯一路徑 dfs2預處理出s到t唯一路徑上每一點下懸掛的最長路徑,用path[i]儲存。 path1[i]表示s選擇在i點離開唯一路徑時,所獲得的最多操作步數 path2[i]表示t選擇在i點離開唯一路徑時,所獲得的最多操作步數 F[][], G[][] 為path1[], path2[]兩陣列rmq詢問前的預處理陣列。 max1(l, r) 表示path1[l].....path1[r]的最大值 max2(l, r) 表示path2[l].....path2[r]的最大值 對抗搜尋,分mode 0,表示s方要最優的決策, mode 1, 表示t方要最優的決策 當狀態遇到(i, j, 0)時,有2種選擇: 1、s方在i點離開2者之間的路徑, 則答案為path1[i] 在這之後,t方的答案就是max2(i + 1, j) //在(i + 1, j)區間中進行rmq詢問。 2、進行狀態(i + 1, j , 1). 同理狀態(i, j, 1); */ #include <bits/stdc++.h> using namespace std; #define N 500005 int n, s, t, to[N << 1], nxt[N << 1], head[N], path[N << 1], inp[N], vis[N], cnt, m; int path1[N << 1], path2[N << 1]; int F[20][N], G[20][N]; int max1(int l,int r) { int x = log2(r - l + 1); return max(F[x][l], F[x][r - (1 << x) + 1]); } int max2(int l,int r) { int x = log2(r - l + 1); return max(G[x][l], G[x][r - (1 << x) + 1]); } void ae(int x,int y) { to[++cnt] = y, nxt[cnt] = head[x], head[x] = cnt; } int dfs1(int u, int t, int dep) { vis[u]=1; if(u == t) { path[dep] = u; inp[u] = 1; return dep; } for(int i = head[u]; i; i = nxt[i]) { int y = to[i]; if(!vis[y]) { int tmp = dfs1(y, t, dep + 1); if(tmp) { path[dep] = u; inp[u] = 1; return tmp; } } } return 0; } int dfs2(int u, int dep) { vis[u] = 1; int tmp = dep; for(int i = head[u]; i; i = nxt[i]) { int y = to[i]; if(!vis[y] && !inp[y]) { tmp = max(tmp, dfs2(y, dep + 1)); } } return tmp; } void init() { for(int i = 1; i <= m; i++) { F[0][i] = path1[i], G[0][i] = path2[i]; } for(int i = 1; i <= 19; i++) { for(int j = 1; j + (1 << (i - 1)) <= m; j++) { F[i][j] = max(F[i - 1][j], F[i - 1][j + (1 << (i - 1))]); } } for(int i = 1; i <= 19; i++) { for(int j = 1; j + (1 << (i - 1)) <= m; j++) { G[i][j] = max(G[i-1][j], G[i - 1][j + (1 << (i - 1))]); } } } int dfs3(int i, int j, int mode) { if(mode == 0) { int score = path1[i] - max2(i + 1, j); if(i + 1 < j) return max(score, -dfs3(i + 1, j, 1)); else return score; } if(mode == 1) { int score = path2[j] - max1(i, j - 1); if(i + 1 < j) return max(score, -dfs3(i, j - 1, 0)); else return score; } } int main() { scanf("%d %d %d", &n, &s, &t); for(int i = 1; i < n; i++) { int ui, vi; scanf("%d %d", &ui, &vi); ae(ui, vi); ae(vi, ui); } memset(vis,0,sizeof(vis)); m = dfs1(s, t, 1); memset(vis, 0, sizeof(vis)); for(int i = 1;i <= m; i++) { path[i] = dfs2(path[i], 0); } for (int i = 1; i <= m; i++) { path1[i] = path[i] + i - 1; path2[i] = path[i] + m - i; } init(); printf("%d\n", dfs3(1, m, 0)); return 0; }