細節很精妙
描述
huyichen世子事件后,xuzhenyi成了皇上特聘的御前一品侍衛。
皇宮以午門為起點,直到后宮嬪妃們的寢宮,呈一棵樹的形狀;某些宮殿間可以互相望見。大內保衛森嚴,三步一崗,五步一哨,每個宮殿都要有人全天候看守,在不同的宮殿安排看守所需的費用不同。
可是xuzhenyi手上的經費不足,無論如何也沒法在每個宮殿都安置留守侍衛。
幫助xuzhenyi布置侍衛,在看守全部宮殿的前提下,使得花費的經費最少。
格式
輸入格式
輸入文件中數據表示一棵樹,描述如下:
第1行 n,表示樹中結點的數目。
第2行至第n+1n+1行,每行描述每個宮殿結點信息,依次為:該宮殿結點標號i(0<i \le n0<i≤n),在該宮殿安置侍衛所需的經費k,該點的兒子數m,接下來m個數,分別是這個節點的m個兒子的標號r_1, r_2, \cdots, r_mr1?,r2?,?,rm?。
對于一個n(0 < n \le 15000<n≤1500)個結點的樹,結點標號在1到n之間,且標號不重復。保證經費總和不超過2^31-1231?1。
輸出格式
輸出文件僅包含一個數,為所求的最少的經費。
題目分析
有些細節處理真的是非常精妙。
分析詳見初涉樹形dp【權最小點覆蓋】vijos1144皇宮看守
1 #include<bits/stdc++.h> 2 const int maxn = 2003; 3 4 int f[maxn][3],a[maxn],n,rt; 5 int head[maxn],nxt[maxn<<1],edges[maxn<<1],edgeTot; 6 bool vis[maxn]; 7 8 int read() 9 { 10 char ch = getchar(); 11 int num = 0; 12 bool fl = 0; 13 for (; !isdigit(ch); ch = getchar()) 14 if (ch=='-') fl = 1; 15 for (; isdigit(ch); ch = getchar()) 16 num = (num<<1)+(num<<3)+ch-48; 17 if (fl) num = -num; 18 return num; 19 } 20 inline int min(int a, int b){return a<b?a:b;} 21 inline int min(int a, int b, int c){int t=min(a,b);return t<c?t:c;} 22 void addedge(int u, int v) 23 { 24 edges[++edgeTot] = v, nxt[edgeTot] = head[u], head[u] = edgeTot; 25 vis[v] = 1; 26 } 27 void dfs(int now) 28 { 29 int delta = 2e9; 30 for (int i=head[now]; i!=-1; i=nxt[i]) 31 { 32 int v = edges[i]; 33 dfs(v); 34 f[now][0] += min(f[v][1], f[v][2]); 35 f[now][1] += min(f[v][1], f[v][2]); 36 delta = min(f[v][2]-f[v][1], delta); 37 f[now][2] += min(f[v][0], f[v][1], f[v][2]); 38 } 39 delta = std::max(delta, 0); 40 f[now][1] += delta; 41 } 42 int main() 43 { 44 memset(head, -1, sizeof head); 45 n = read(); 46 for (int i=1; i<=n; i++) 47 { 48 int p = read(), k; 49 f[p][2] = a[p] = read(), k = read(); 50 while (k--) addedge(p, read()); 51 } 52 rt = 1; 53 while (vis[rt]) rt++; 54 dfs(rt); 55 printf("%d\n",min(f[rt][1], f[rt][2])); 56 return 0; 57 }
?
?
?
END