1. 程式人生 > >百練3383:Cell Phone Network

百練3383:Cell Phone Network

%d ble set 實現 names sca amp register can

傳送門:http://bailian.openjudge.cn/practice/3383/

【題解】

題目就是最小支配集。

學習了最小支配集的解法:

樹形dp(有空可以推一推)

貪心:DFS遍歷後逆DFS序進行處理,如果當前這個點不在支配集而且沒和支配集連邊,那麽標記它父親為支配集成員並處理父親的父親和自己(標為和支配集連邊的)

具體實現用一個數組記錄支配集一個數組記錄是否是支配集 or 連過邊。

技術分享
# include <stdio.h>
# include <string.h>
# include <iostream>
# include <algorithm>
//
# include <bits/stdc++.h> using namespace std; typedef long long ll; typedef long double ld; typedef unsigned long long ull; const int M = 5e5 + 10; const int mod = 1e9+7; # define RG register # define ST static /* 首先選擇一點為樹根,再按照深度優先遍歷得到遍歷序列,按照所得序列 的反向序列的順序進行貪心,對於一個即不屬於支配集也不與支配集中的 點相連的點來說,如果他的父節點不屬於支配集,將其父節點加入到支配集
*/ int n; int head[M], nxt[M], to[M], tot=0; bool s[M], is[M]; // have been covered yet(in set or connected with ... in set), in set inline void add(int u, int v) { ++tot; nxt[tot] = head[u]; head[u] = tot; to[tot] = v; } inline void adde(int u, int v) { add(u, v), add(v, u); } int dfn[M], DFN=0
, fa[M]; inline void dfs(int x, int fat) { ++DFN; fa[x] = fat; dfn[DFN] = x; for (int i=head[x]; i; i=nxt[i]) if(to[i] != fat) dfs(to[i], x); } int main() { while(cin >> n) { memset(head, 0, sizeof head); tot = 0; DFN = 0; memset(s, 0, sizeof s); memset(is, 0, sizeof is); memset(fa, 0, sizeof fa); for (int i=1, u, v; i<n; ++i) { scanf("%d%d", &u, &v); adde(u, v); } dfs(1, 1); for (int i=n; i>=1; --i) { int x = dfn[i]; if(!s[x]) { if(!is[fa[x]]) is[fa[x]] = 1; s[x] = 1; s[fa[x]] = 1; s[fa[fa[x]]] = 1; } } int ans = 0; for (int i=1; i<=n; ++i) ans += is[i]; if(n == 1) puts("1"); else printf("%d\n", ans); } return 0; }
View Code

百練3383:Cell Phone Network