1001 小G有一个大树 dfs 树形DP
链接:https://ac.nowcoder.com/acm/contest/25022/1001
来源:牛客网
题目描述
小G想要把自己家院子里的橘子树搬到家门口(QAQ。。就当小G是大力水手吧) 可是小G是个平衡性灰常灰常差的人,他想找到一个这个橘子树的平衡点。 怎么描述这棵树呢。。。就把它看成由一个个节点构成的树吧。结点数就 代表树重。
输入描述:
多组数据输入输出,
第一行包含一个整数n(3<=n<=1000)代表树的结点的个数
以下n-1行描述(1-n)节点间的连接关系。
输出描述:
输出两个个整数 x,num 分别代表树的平衡点,和删除平衡点后最大子树的结点数(如果结点数相同输出编号小的)。
分析
平衡点:删除某个节点后,形成的多颗树的最大节点数最小。
深度优先搜索一下,算一下每个节点的子树大小,取最大值,然后ans取每个节点的最小值,那个最小值所在的点就是平衡点。
//-------------------------代码---------------------------- //#define int ll const int N = 1e5+10; int n,m; int ans = inf; int sz[N],p,cnt = 0; void dfs(int u,int fa,V<int> g[]) { int res = 0;cnt ++ ; // if(cnt == 50) {bd;gg;} for(int i = 0;i<g[u].size();i ++ ) { if(g[u][i] == fa) continue; dfs(g[u][i],u,g); sz[u] += sz[g[u][i]]; res = max(sz[g[u][i]],res); } sz[u] += 1; res = max(res,n-sz[u]); if(res < ans) { ans = res; p = u; } } void solve() { ans = inf; ms(sz,0); cin>>n; V<int> g[n+1]; V<bool > vis(n+1); fo(i,1,n-1) { int a,b;cin>>a>>b; g[a].pb(b); vis[b] = 1; } int root; fo(i,1,n) { if(vis[i] == 0) { root = i; break; } } dfs(root,-1,g); cout<<p<<' ' << ans<<endl; } signed main(){ clapping();TLE; // int t;cin>>t;while(t -- ) solve(); // {solve(); } return 0; } /*样例区 */ //------------------------------------------------------------