您的位置:首页 > 大数据 > 人工智能

AIM Tech Round 3 (Div. 2) E. Centroids (树形dp) ★ ★ ★

2016-10-13 21:55 357 查看
题意:规定一个树上操作:删掉一个树边,这样会变成两棵树,然后把其中一棵的断点接到另一棵树上的任何一个节点上。问你对于树上每一个节点,能不能通过最多一次的修改操作,把该点变为树的重心。如果该点可以就输出1,否则输出0。

题解:枚举每个节点作为根,那么这个节点的子树中,如果只有一个大于n/2,那么就从这个子树中抽取一个最大的不超过n/2的子树,然后接到当前根,如果这个子树还是大于n/2,或者还有子树大于n/2,那么这两种情况是不可以的。

dfs_down跑一遍,把每个节点u为根的其中一棵子树大小dw跑出来,然后跑出来以u为根的一子树中不超n/2的最大的子树,再max一下大小。

dfs_up跑一遍,把另外一棵子树up也跑出来。然后再枚举每个节点的子树,再与n/2比较一下就可以啦。

#pragma comment(linker, "/STACK:102400000,102400000")
//#include<bits/stdc++.h>
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<iostream>
#include<cstring>
#include<vector>
#include<map>
#include<cmath>
#include<queue>
#include<set>
#include<stack>
#include <utility>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> pii;
#define mst(a) memset(a, 0, sizeof(a))
#define M_P(x,y) make_pair(x,y)
#define in freopen("in.txt","r",stdin)
#define rep(i,j,k) for (int i = j; i <= k; i++)
#define per(i,j,k) for (int i = j; i >= k; i--)
#define lson x << 1, l, mid
#define rson x << 1 | 1, mid + 1, r
const int lowbit(int x) { return x&-x; }
const double eps = 1e-8;
const int INF = 1e9+7;
const ll inf =(1LL<<62) ;
const int MOD = 1e9 + 7;
const ll mod = (1LL<<32);
const int N =1e6+6;
const int M=100010;
const int maxn=1001;
template <class T1, class T2>inline void getmax(T1 &a, T2 b) {if (b>a)a = b;}
template <class T1, class T2>inline void getmin(T1 &a, T2 b) {if (b<a)a = b;}
int read(){
int v = 0, f = 1;char c =getchar();
while( c < 48 || 57 < c ){if(c=='-') f = -1;c = getchar();}
while(48 <= c && c <= 57) v = v*10+c-48, c = getchar();
return v*f;}
int n;
int sz
,par
;
int up
, dw
; //两棵子树
vector<int> adj
; //邻接矩阵
void dfs_sz(int v, int p =-1)
{
par[v] = p;
sz[v] = 1;
for(auto u : adj[v])
{
if (u != p){
dfs_sz(u,v);
sz[v] += sz[u];
}
}
}
void dfs_down(int v, int p = -1) //一子树
{
dw[v] = (sz[v] <= n / 2 ? sz[v]: 0);
for (auto u : adj[v])
{
if(u != p)
{
dfs_down(u,v);
dw[v] = max(dw[v],dw[u]);
}
}
}
void dfs_up(int v, int val = 0, int p = -1) //二子树
{
up[v] = max((n - sz[v] <= n / 2 ? n - sz[v]: 0), val);
int mx0 = 0, mx1 = 0;
for(auto u : adj[v])
{
if(u != p)
{
if(dw[u] >= mx0){
mx1 = mx0;
mx0 = dw[u];
}
else if(dw[u] >= mx1){
mx1 = dw[u];
}
}
}
for (auto u : adj[v])
{
if(u != p)
{
dfs_up(u, max(up[v], mx0 == dw[u] ? mx1 : mx0), v);
}
}
}
int main()
{
int u,v;
cin>>n;
for(int i=0;i<n-1;i++)
{
cin>>u>>v;
--u, --v;
adj[u].push_back(v);
adj[v].push_back(u);
}
dfs_sz(0);
dfs_down(0);
dfs_up(0);

for(int v = 0; v < n; v++) //枚举每个节点u作为根
{
int ans = 1;
for(auto u : adj[v])
{
if(u == par[v])
{
if (n - sz[v] - up[v] > n / 2)
ans = 0;
}
else
{
if(sz[u] - dw[u] > n / 2)
ans = 0;
}
}
cout <<ans<<' ';
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: