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

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

2016-08-26 00:27 381 查看
E. Centroids

time limit per test
4 seconds

memory limit per test
512 megabytes

input
standard input

output
standard output

Tree is a connected acyclic graph. Suppose you are given a tree consisting of n vertices.
The vertex of this tree is called centroid if the size of each connected component that appears if this vertex is removed from the tree doesn't exceed 

.

You are given a tree of size n and can perform no more than one edge replacement. Edge
replacement is the operation of removing one edge from the tree (without deleting incident vertices) and inserting one new edge (without adding new vertices) in such a way that the graph remains a tree. For each vertex you have to determine if it's
possible to make it centroid by performing no more than one edge replacement.

Input

The first line of the input contains an integer n (2 ≤ n ≤ 400 000) —
the number of vertices in the tree. Each of the next n - 1 lines contains a pair of vertex indices ui and vi (1 ≤ ui, vi ≤ n) —
endpoints of the corresponding edge.

Output

Print n integers. The i-th
of them should be equal to 1 if the i-th vertex can
be made centroid by replacing no more than one edge, and should be equal to 0 otherwise.

Examples

input
3
1 2
2 3


output
1 1 1


input
5
1 2
1 3
1 4
1 5


output
1 0 0 0 0


Note

In the first sample each vertex can be made a centroid. For example, in order to turn vertex 1 to centroid one have to replace the
edge(2, 3) with the edge (1, 3).

题意:规定一个树上操作:删掉一个树边,这样会变成两棵树,然后把其中一棵的断点接到另一棵树上的任何一个节点上。问你对于树上每一个节点,能不能通过最多一次的修改操作,把该点变为树的重心。如果该点可以就输出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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: