題目: UVa - 12442 - Forwarding Emails
題目說明
有一個小鎮,裡面的居民每個人都只會給另一個人寄信,求把信寄給哪位居民可以讓最多人看到這封信,若有相同者則取較小者。
Input: 第一行為一整數 T
,代表有 T
組測資,每組測資的第一行為一整數 N
,接下來 N
行每行都有兩個整數 u
、v
,代表居民 u
會把信寄給居民 v
。
Output: 輸出寄信給誰可以讓最多的居民看到這封信,若有相同者則取較小者。
解題思路
DFS 模擬即可,由於會 TLE,所以進行一點剪枝,多使用一個陣列紀錄某位居民是否已經被模擬過了,若在前面被模擬過了則就不需要在模擬第一個寄信給這位居民了,因為前面模擬的是另一個居民會寄給這位居民,一定會比直接寄信給這位居民的人數還要多。例如:
1 2 3 4 5 6 7 8
| 若居民有 3 人,且寄信關係為:
1 3 2 3 3 2
則寄信給第一位居民時會再寄給第三位居民,那遍歷到第三位居民時就不需要在模擬一次了, 因為由第一位寄給第三位,一定會比直接寄給第三位多。
|
參考解法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62
| #include <iostream> #include <functional> #include <climits> #include <vector>
#define LOOP(n) for(int I = 0; I < n; ++I)
using namespace std;
static auto __ = [] { ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0); return 0; }();
int main() { int T; cin >> T;
LOOP(T) { int N; cin >> N;
vector<int> adj(N + 1); LOOP(N) { int u, v; cin >> u >> v; adj[u] = v; }
int _max = INT_MIN, ret = 0; vector<bool> visited(N + 1), dfsV;
function<int(int)> dfs = [&](int u) -> int { if (dfsV[u]) return 0; visited[u] = dfsV[u] = true; return 1 + dfs(adj[u]); };
for (int i = 1; i <= N; ++i) { if (visited[i]) continue;
dfsV.assign(N + 1, false); int tmp = dfs(i); if (tmp > _max) _max = tmp, ret = i; }
cout << "Case " << I + 1 << ": " << ret << '\n'; } }
|
參考資料
[UVA] 12442 - Forwarding Emails