标签:color main lines tin names number sid miss and
Time Limit: 1000MS | Memory Limit: 65536K | |
Total Submissions: 14247 | Accepted: 6026 |
1 7 2 6 1 2 1 4 4 5 3 7 3 1
1 2
找树的重心,即:
定义1:找到一个点,其所有的子树中最大的子树节点数最少,那么这个点就是这棵树的重心。
定义2:以这个点为根,那么所有的子树(不算整个树自身)的大小都不超过整个树大小的一半。
性质1:树中所有点到某个点的距离和中,到重心的距离和是最小的;如果有两个重心,那么他们的距离和一样。
性质2:把两个树通过一条边相连得到一个新的树,那么新的树的重心在连接原来两个树的重心的路径上。
性质3:把一个树添加或删除一个叶子,那么它的重心最多只移动一条边的距离。
选取任意节点为根节点,dfs求当前节点所代表的子树的节点总数(包含自己记为sum)和该节点的所有子树中节点数最大值(记为ave)。则依据题意,删除当前节点后的平衡值为
max(n-sum,ave);找到最小值输出。
看到别人说是dp,可能我不会dp。
#include<iostream> #include<cstdio> #include<vector> using namespace std; const int maxn = 2e4+4, INF = 0x3f3f3f3f; vector<int> grap[maxn]; int vis[maxn], sum[maxn], ave[maxn]; int t, n; int dfs(int x) { int res=1; for(int i=0; i<grap[x].size(); ++i) { int xx=grap[x][i]; if(vis[xx]) continue; vis[xx]=1; int kk=dfs(xx); ave[x]=max(ave[x], kk); res+=kk; vis[xx]=0; } sum[x]=res; ave[x]=max(ave[x], n-sum[x]); return res; } int main() { ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); cin>>t; while(t--) { cin>>n; for(int i=1; i<=n; ++i) { grap[i].clear(); vis[i]=0; sum[i]=0; ave[i]=0; } for(int i=2; i<=n; ++i) { int u, v; cin>>u>>v; grap[u].push_back(v); grap[v].push_back(u); } vis[1]=1; dfs(1); int ans=INF, v=0; for(int i=1; i<=n; ++i) if(ans>ave[i]) ans=ave[i], v=i; cout<<v<<" "<<ans<<endl; } return 0; }
poj1655 Balancing Act (dp? dfs?)
标签:color main lines tin names number sid miss and
原文地址:http://www.cnblogs.com/xiepingfu/p/7280150.html