初学树形dp,看着雨聚聚的PPT上思路搞出来了。。。
题目意思:找到一个割点,树将被割成两个部分,找到最大的连通块。
状态转移方程:F[i]=max(max(tot[k]),n-tot[i]] (k是i的子树)
然后dfs的时候把状态转移方程带进去就好了,注意每一次都得把自己这个点算上。
另外,为了防止对树进行深搜的时候,因为是一个无向图,会来回往复,每一次记录前一个结点的编号,有效防止“走回头路”
#include <bits/stdc++.h> using namespace std; vector <int> G[1010]; int dp[1010]; int ansx,ansnum; int n; void dfs(int u,int pre) { dp[u]=1; int m=0; for(int i=0;i<G[u].size();i++) { if(G[u][i]==pre) continue; dfs(G[u][i],u); dp[u]+=dp[G[u][i]]; m=max(m,dp[G[u][i]]); } m=max(m,n-dp[u]); if(m<ansnum) { ansnum=m; ansx=u; } else if(m==ansnum) { if(ansx>u) ansx=u; } } int main() { while(scanf("%d",&n)!=EOF) { for(int i=1;i<=n;i++) { G[i].clear(); dp[i]=0; } for(int i=1;i<n;i++) { int u,v; scanf("%d%d",&u,&v); G[u].push_back(v); G[v].push_back(u); } } ansx=ansnum=0x3f3f3f3f; dfs(1,0); printf("%d %d\n",ansx,ansnum); }