1. 程式人生 > >BZOJ 3391 [Usaco2004 Dec]Tree Cutting網絡破壞

BZOJ 3391 [Usaco2004 Dec]Tree Cutting網絡破壞

logs amp sin spa nbsp pre using 產生 -s

實現不難,對我這種辣雞來說有一定的思維量。

對於每個點我們只需要知道它的子樹大小的總和和它最大的子樹大小是多少就可以了。

因為對於每個點 只要知道了它的子樹大小的總和那麽也就知道了 它的所有父親以及兄弟的數量(n-子樹大小)

因為對於這個點來說,割去後對答案產生影響的只有它最大的子樹大小。

如果割去這個點後 它的所有父親以及兄弟的數量<=n/2 同時 最大的子樹大小也<=n/2

那麽一定是可行的。

#include <cstdio>
#include <algorithm>

using std::max;

struct node{
    
int u,v,next; node(){} node(int _u,int _v,int _next){ u = _u; v = _v; next = _next; } }Edge[20005]; int n,head[20005],Count; int sum[20005],Max[20005]; inline void AddEdge(int u,int v){ Count++; Edge[Count] = node(u,v,head[u]); head[u] = Count; }
void dfs(int x,int fa){ sum[x]=1; for(int i=head[x];i;i=Edge[i].next){ int v = Edge[i].v; if(v==fa) continue; dfs(v,x); sum[x]+=sum[v]; } for(int i=head[x];i;i=Edge[i].next){ int v = Edge[i].v; Max[x] = max(Max[x],sum[v]); } }
int main(){ scanf("%d",&n); for(int i=1;i<n;i++){ int u,v; scanf("%d%d",&u,&v); AddEdge(u,v); AddEdge(v,u); } dfs(1,-1); int limit = n/2; for(int i=1;i<=n;i++){ if(n-sum[i]<=limit && Max[i] <= limit ) printf("%d\n",i); } return 0; }

BZOJ 3391 [Usaco2004 Dec]Tree Cutting網絡破壞