1. 程式人生 > >UVa Live 3683 A Scheduling Problem - 動態規劃

UVa Live 3683 A Scheduling Problem - 動態規劃

cto scanf -c bool 題目 inf namespace pro 指向

題目傳送門

  傳送門

題目大意

  給定一個樹,其中有一些邊已經定向,要求為剩下的邊定向使得最長路最短。

定理 答案不會超過定向前由已經定向的邊組成的最長路的長度加1。

  我也不會證明qwq。

  假設當前由已經定向的邊組成的最長路的長度為$L$,那麽只用判定答案是否能是$L$。

  考慮對於一個未定向的邊$(u, v)$($u$的深度更淺)我們給它定向,不妨設它的方向是指向父節點。

  那麽在$v$的子樹中方向向$v$的子樹內的有向路徑對當前的點沒有影響。

  因此我們只用考慮求出每個點滿足條件的時候,以它作為起點的時候,方向向子樹內的最長有向路徑的最小長度,以及當它作為終點的時候,子樹內方向向父節點的最長有向路徑的最小長度。

  考慮怎麽計算它們。

  首先已經被定向的邊無力改變。

  對於還未定向的邊連接的子樹,考慮將它們按照某一種權值排序,然後枚舉這種權值的最大值,再記錄另一種權值的後綴最大值,判斷是否合法,合法就更新上面兩個值,如果不合法就改成$\infty$。再對另外一種權值做一遍。

  時間復雜度$O(n\log n)$

Code

  1 /**
  2  * UVa Live
  3  * Problem#3683
  4  * Accepted
  5  * Time: 0ms
  6  */
  7 #include <algorithm>
  8 #include <iostream>
  9
#include <cstdlib> 10 #include <cstdio> 11 #include <vector> 12 using namespace std; 13 typedef bool boolean; 14 15 const signed int inf = (signed) (~0u >> 3); 16 17 const int N = 205; 18 19 typedef pair<int, int> pii; 20 21 template <typename T> 22
void pfill(T* pst, const T* ped, T val) { 23 for ( ; pst != ped; *(pst++) = val); 24 } 25 26 typedef class Edge { 27 public: 28 int ed, nx, rev; // rev = 0: undirected, rev = 1: positive order, rev = -1: reverse order 29 30 Edge(int ed = 0, int nx = 0, int rev = 0):ed(ed), nx(nx), rev(rev) { } 31 }Edge; 32 33 typedef class MapManager { 34 public: 35 int h[N]; 36 vector<Edge> es; 37 38 void init(int n) { 39 pfill(h + 1, h + n + 1, -1); 40 es.clear(); 41 } 42 43 void addEdge(int u, int v, int rev) { 44 es.push_back(Edge(v, h[u], rev)); 45 h[u] = (signed) es.size() - 1; 46 } 47 48 Edge& operator [] (int p) { 49 return es[p]; 50 } 51 }MapManager; 52 53 int n, m; 54 MapManager g; 55 boolean vis[N]; 56 int fu[N], fd[N], d[N]; 57 58 inline boolean init() { 59 static int u, v; 60 static char buf[12], *c; 61 62 boolean aflag = false; 63 g.init(N - 1); 64 while (~scanf("%d", &u) && u) { 65 aflag = true; 66 n = max(n, u); 67 while (~scanf("%s", buf) && buf[0] != 0) { 68 for (v = 0, c = buf; *c >= 0 && *c <= 9; v = v * 10 + *c - 0, c++); 69 n = max(n, v); 70 if (*c == d) { 71 g.addEdge(u, v, 1); 72 g.addEdge(v, u, -1); 73 } else if (*c == u) { 74 g.addEdge(u, v, -1); 75 g.addEdge(v, u, 1); 76 } else { 77 g.addEdge(u, v, 0); 78 g.addEdge(v, u, 0); 79 } 80 81 // cerr << u << " " << v << ‘\n‘; 82 } 83 } 84 85 return aflag; 86 } 87 88 int dfs(int p, int fa) { 89 if (vis[p]) 90 return d[p]; 91 vis[p] = true, d[p] = 1; 92 for (int i = g.h[p], e; ~i; i = g[i].nx) { 93 if (((e = g[i].ed) ^ fa) && g[i].rev == 1) 94 d[p] = max(d[p], dfs(e, p) + 1); 95 } 96 return d[p]; 97 } 98 99 int res; 100 void dp_main(int p, int fa) { 101 static pii tmp[N]; 102 103 int max_up = 0, max_do = 0, tp = 0; 104 for (int i = g.h[p], e; ~i; i = g[i].nx) { 105 if ((e = g[i].ed) == fa) 106 continue; 107 dp_main(e, p); 108 109 if (g[i].rev == 1) 110 max_do = max(max_do, fd[e]); 111 if (g[i].rev == -1) 112 max_up = max(max_up, fu[e]); 113 } 114 115 for (int i = g.h[p], e; ~i; i = g[i].nx) { 116 if ((e = g[i].ed) == fa || g[i].rev) 117 continue; 118 tmp[++tp] = pii(fd[e], fu[e]); 119 } 120 121 fd[p] = fu[p] = inf; 122 if (!tp) { 123 if (max_do + max_up + 1 <= res) { 124 fd[p] = max_do + 1; 125 fu[p] = max_up + 1; 126 } 127 return ; 128 } 129 130 tmp[++tp] = pii(0, 0); 131 sort(tmp + 1, tmp + tp + 1, [&] (const pii& a, const pii& b) { return a.first < b.first; }); 132 133 int mx = 0; 134 for (int i = tp; i; i--) { 135 if (max(tmp[i].first, max_do) + max(mx, max_up) + 1 <= res) 136 fd[p] = max(tmp[i].first, max_do) + 1; 137 mx = max(mx, tmp[i].second); 138 } 139 140 sort(tmp + 1, tmp + tp + 1, [&] (const pii& a, const pii& b) { return a.second < b.second; }); 141 142 mx = 0; 143 for (int i = tp; i; i--) { 144 if (max(tmp[i].second, max_up) + max(mx, max_do) + 1 <= res) 145 fu[p] = max(tmp[i].second, max_up) + 1; 146 mx = max(mx, tmp[i].first); 147 } 148 // cerr << p << " " << fu[p] << " " << fd[p] << ‘\n‘; 149 } 150 151 inline void solve() { 152 res = 0; 153 pfill(vis + 1, vis + n + 1, false); 154 for (int i = 1; i <= n; i++) { 155 res = max(res, dfs(i, 0)); 156 if (res == 4) 157 cerr << i << \n; 158 } 159 // cerr << res << ‘\n‘; 160 dp_main(1, 0); 161 printf("%d\n", res + (fu[1] + fd[1] - 1 > res)); 162 } 163 164 int main() { 165 while (init()) 166 solve(); 167 return 0; 168 }

UVa Live 3683 A Scheduling Problem - 動態規劃