1. 程式人生 > >UVa Live 3683 A Scheduling Problem

UVa Live 3683 A Scheduling Problem

題目傳送門

  傳送門

題目大意

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

定理 答案不會超過定向前由已經定向的邊組成的最長路的長度加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 - 動態規劃

cto scanf -c bool 題目 inf namespace pro 指向 題目傳送門   傳送門 題目大意   給定一個樹,其中有一些邊已經定向,要求為剩下的邊定向使得最長路最短。 定理 答案不會超過定向前由已經定向的邊組成的最長路的長度加

UVa Live 3683 A Scheduling Problem

題目傳送門   傳送門 題目大意   給定一個樹,其中有一些邊已經定向,要求為剩下的邊定向使得最長路最短。 定理 答案不會超過定向前由已經定向的邊組成的最長路的長度加1。   我也不會證明qwq。   假設當前由已經定向的邊組成的最長路的長度為$L$,那麼只用判定答案是否能是$

UVa #1380 A Scheduling Problem (例題9-26)

居然一次就過了。。做了兩天,淚流滿面啊。不過程式碼跑得很慢。。有機會優化一下 這道題想清楚了還是很簡單的,但是一開始的思路不容易理順。下面文中我的f和g與Rujia書中的定義相反,請注意區分。 題目裡說,把所有的無向邊去掉之後,最終答案則一定是由剩下的有向邊組成的最長路

UVA - 387 A Puzzling Problem

題目連結: https://vjudge.net/problem/UVA-387 思路: 非常有意思的拼圖,深搜+回溯, 輸出硬傷:除了第一次之外,每次先輸空格,再輸出結果, 以及可能給的資料拼不成4*4表格的情況。 #include<iostream> #include<

P1865 A % B Problem

code 輸入輸出 說明 tin else 描述 sca ++ return 題目背景 題目名稱是吸引你點進來的 實際上該題還是很水的 題目描述 區間質數個數 輸入輸出格式 輸入格式: 一行兩個整數 詢問次數n,範圍m 接下來n行,每行兩個整數 l,r

poj3511--A Simple Problem with Integers(線段樹求和)

poj pac style som can com onos roman miss A Simple Problem with Integers Time Limit: 5000MS Memory Limit: 131072K

【數論線性篩】洛谷P1865 A%B problem

continue 個數 區間 str 輸出 數據 兩個 裸題 n) 題目背景 題目名稱是吸引你點進來的 實際上該題還是很水的 題目描述 區間質數個數 輸入輸出格式 輸入格式: 一行兩個整數 詢問次數n,範圍m 接下來n行,每行兩個整數 l,r 表示區間 輸出格式:

P1303 A*B Problem

cst clu ont tdi cnblogs ring b- max can 題目描述 求兩數的積。 輸入輸出格式 輸入格式: 兩個數 輸出格式: 積 輸入輸出樣例 輸入樣例#1: 1 2

線段樹專題 POJ3468 A Simple Problem with Integers

strong print style update else algo linker clas uil 題意:n個點。m個操作。兩種操作類型。C X Y K 表示區間[x,y]上每一個點值加k。Q X Y 求區間[x,y]的和 分析:線段樹區間求和,裸模板 註意

HDOJ1002-A + B Problem II(高精加)

change test case logs names div lar struct () har Problem Description I have a very simple problem for you. Given two integers A and B,

poj 3468 A Simple Problem with Integers

arch fin uil range swe next char () limit A Simple Problem with Integers Time Limit: 5000MS Memory Limit: 131072K Total

HDU 1402 A * B Problem Plus FFT

contain linker pri span stack pragma mod exce problem A * B Problem Plus Problem Description Calculate A * B. Input Each line

loj6157 A^B Problem (並查集)

所有 是否 一個點 ron blank problem 異或 loj 遍歷 題目: https://loj.ac/problem/6157 分析: 這種樹上異或,一般是采用分位考慮,但是這題即使分位,也會發現非常不好處理 這裏考慮維護一個點到其根的路徑的異或值 用

A Simple Problem About Truth Table

函數定義 進制轉換 blog binary expr cas 初始化 表達 n) 源代碼: #include<iostream> #include<string> #include<cmath> using namespace std

HPU 1002 A + B Problem II【大數】

lar 保存 memory positive test size mod ack auth A + B Problem II Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/327

poj 3468 A Simple Problem with Integers(原來是一道簡單的線段樹區間修改用來練練splay)

long 兩個 可能 style push ios stream 區間 pan 題目鏈接:http://poj.org/problem?id=3468 題解:splay功能比線段樹強大當然代價就是有些操作比線段樹慢,這題用splay實現的比線段樹慢上一倍。線段樹用l

Week 1 # A A + B Problem II

res lines osi 可能 c代碼 turn contains inpu mean 原題描述: A - A + B Problem II I have a very simple problem for you. Given two integers A and B,

uva 1378 - A Funny Stone Game sg博弈

1.0 mat cto i+1 clas typedef article 移動 post 題意:David 玩一個石子遊戲。遊戲中,有n堆石子,被編號為0..n-1。兩名玩家輪流取石子。 每一輪遊戲。每名玩家選取3堆石子i,j,k(i<j,j<=k,且至

luogu1001 A+B Problem

而且 clas printf 一個 include main函數 int () div A+B Problem 題目描述 輸入兩個整數a,b,輸出它們的和(|a|,|b|<=10^9)。 註意 1、pascal使用integer會爆掉哦! 2、有負數哦! 3、c/c+

HDU 1402 A * B Problem Plus ——(大數乘法,FFT)

兩個 ret 處理 complex truct std spa strlen mes   因為剛學fft,想拿這題練練手,結果WA了個爽= =。   總結幾點犯的錯誤:   1.要註意處理前導零的問題。   2.一定要註意數組大小的問題。(前一個fft的題因為沒用到b數組,