1. 程式人生 > >Codeforces 835F Roads in the Kingdom - 動態規劃

Codeforces 835F Roads in the Kingdom - 動態規劃

com content AS == clas turn std new void

題目傳送門

  傳送點I

  傳送點II

  傳送點III

題目大意

  給定一顆基環樹,要求刪去其中一條邊,使得剩下的圖形是一棵樹,並且最長路的長度最短,求最長路的最短長度。

  路徑可以分為兩部分:跨過環 和 在樹內部。

  要刪除一條邊,使圖形變為一棵樹,那麽只能刪去環上的一條邊,因此,我們無法改變第二部分的路徑,但是可以改變第一部分。

  對於第二部分可以通過兩次搜索或者樹形動態規劃解決。

  對於第一部分,考慮枚舉刪去環上的一條邊。但是發現仍然不太方便處理,因為不好維護環上的信息。仍然考慮剖環成鏈。

  假設環的大小為$k$,從剖點開始依次將所有點標號1到$k$。

  當一條邊被刪除後,第二部分可能成為答案的情況有兩種:

  1. 不跨過剖點和被刪邊的路徑
  2. 跨過剖點但不經過被刪邊的路徑

  因此考慮維護一些數組。

  1. 在$1, 2, \cdots, i$及其所在的樹中的最長路。
  2. 從$1$開始,到$1, 2, \cdots, i$及其所在的樹中的最長路。
  3. 在$k, k - 1, \cdots, i$及其所在的樹中的最長路。
  4. 從$k$開始,到$k, k - 1, \cdots, i$及其所在的樹中的最長路。

  這四個部分都可以線性預處理出來。然後枚舉刪掉的環邊就能統計第一部分的答案。

Code

  1 /**
  2  * Codeforces
3 * Problem#835F 4 * Accepted 5 * Time: 155ms 6 * Memory: 27100k 7 */ 8 #include <bits/stdc++.h> 9 #ifndef WIN32 10 #define Auto "%lld" 11 #else 12 #define Auto "%I64d" 13 #endif 14 using namespace std; 15 typedef bool boolean; 16 17 typedef class Edge {
18 public: 19 int ed, nx, w; 20 21 Edge(int ed = 0, int nx = 0, int w = 0):ed(ed), nx(nx), w(w) { } 22 }Edge; 23 24 typedef class MapManager { 25 public: 26 int ce; 27 int* h; 28 Edge* es; 29 30 MapManager() { } 31 MapManager(int n, int m):ce(-1) { 32 h = new int[(n + 1)]; 33 es = new Edge[(m + 1)]; 34 memset(h, -1, sizeof(int) * (n + 1)); 35 } 36 37 void addEdge(int u, int v, int w) { 38 es[++ce] = Edge(v, h[u], w); 39 h[u] = ce; 40 } 41 42 Edge& operator [] (int pos) { 43 return es[pos]; 44 } 45 }MapManager; 46 47 #define ll long long 48 49 const signed ll llf = (signed ll) ((~0ull) >> 1); 50 51 int n; 52 int ccir, cc; 53 MapManager g; 54 stack<int> s; 55 boolean *vis, *icir; 56 int *cir, *nw; 57 ll *ap[2], *cp[2], *dep, *dis; 58 59 inline void init() { 60 scanf("%d", &n); 61 vis = new boolean[(n + 1)]; 62 icir = new boolean[(n + 1)]; 63 cir = new int[(n + 1)]; 64 nw = new int[(n + 1)]; 65 dep = new ll[(n + 1)]; 66 dis = new ll[(n + 1)]; 67 for (int i = 0; i < 2; i++) { 68 ap[i] = new ll[(n + 1)]; 69 cp[i] = new ll[(n + 1)]; 70 } 71 g = MapManager(n, n << 1); 72 memset(vis, false, sizeof(boolean) * (n + 1)); 73 memset(icir, false, sizeof(boolean) * (n + 1)); 74 for (int i = 1, u, v, w; i <= n; i++) { 75 scanf("%d%d%d", &u, &v, &w); 76 g.addEdge(u, v, w); 77 g.addEdge(v, u, w); 78 } 79 } 80 81 boolean getLoop(int p, int fa) { 82 if (vis[p]) { 83 ccir = 0; 84 int cur = 0; 85 do { 86 cur = s.top(); 87 s.pop(); 88 icir[cur] = true; 89 cir[ccir++] = cur; 90 cc = ccir - 1; 91 } while (cur != p); 92 return true; 93 } 94 vis[p] = true; 95 s.push(p); 96 for (int i = g.h[p]; ~i; i = g[i].nx) { 97 int e = g[i].ed; 98 if (e == fa) continue; 99 if (getLoop(e, p)) { 100 if (icir[p]) { 101 nw[cc] = g[i].w; 102 cc = (cc + 1) % ccir; 103 } 104 return true; 105 } 106 } 107 s.pop(); 108 return false; 109 } 110 111 void dfs(int p, int fa, ll dep, int& fn, ll& fd) { 112 if (dep > fd) 113 fd = dep, fn = p; 114 for (int i = g.h[p]; ~i; i = g[i].nx) { 115 int e = g[i].ed; 116 if (e == fa || icir[e]) continue; 117 dfs(e, p, dep + g[i].w, fn, fd); 118 } 119 } 120 121 inline void solve() { 122 getLoop(1, 0); 123 ll fixedd = 0; 124 // for (int i = 0; i < ccir; i++) 125 // cerr << cir[i] << " "; 126 // cerr << endl; 127 // for (int i = 0; i < ccir; i++) 128 // cerr << nw[i] << " "; 129 // cerr << endl; 130 for (int i = 0, fn, fbn; i < ccir; i++) { 131 fn = -1, dep[i] = 0; 132 dep[i] = 0, dfs(cir[i], 0, 0, fn, dep[i]); 133 if (~fn) 134 icir[cir[i]] = false, dfs(fn, 0, 0, fbn, fixedd), icir[cir[i]] = true; 135 } 136 dis[0] = 0; 137 for (int i = 1; i < ccir; i++) 138 dis[i] = nw[i - 1]; 139 for (int i = 1; i < ccir; i++) 140 dis[i] += dis[i - 1]; 141 ll mi = dep[0]; 142 ap[0][0] = -llf, cp[0][0] = dep[0]; 143 for (int i = 1; i < ccir; i++) { 144 ap[0][i] = max(ap[0][i - 1], dep[i] + dis[i] + mi); 145 mi = max(mi, dep[i] - dis[i]); 146 cp[0][i] = max(cp[0][i - 1], dep[i] + dis[i]); 147 } 148 mi = dep[ccir - 1] + dis[ccir - 1]; 149 ap[1][ccir - 1] = -llf, cp[1][ccir - 1] = dep[ccir - 1]; 150 for (int i = ccir - 2; ~i; i--) { 151 ap[1][i] = max(ap[1][i + 1], dep[i] - dis[i] + mi); 152 mi = max(mi, dep[i] + dis[i]); 153 cp[1][i] = max(cp[1][i + 1], dep[i] + dis[ccir - 1] - dis[i]); 154 } 155 ll ans = ap[0][ccir - 1]; 156 for (int i = 0; i < ccir - 1; i++) 157 ans = min(max(max(ap[0][i], ap[1][i + 1]), cp[0][i] + cp[1][i + 1] + nw[ccir - 1]), ans); 158 printf(Auto, max(ans, fixedd)); 159 } 160 161 int main() { 162 init(); 163 solve(); 164 return 0; 165 }

Codeforces 835F Roads in the Kingdom - 動態規劃