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

题意:规定一个树上操作:删掉一个树边,这样会变成两棵树,然后把其中一棵的断点接到另一棵树上的任何一个节点上。问你对于树上每一个节点,能不能通过最多一次的修改操作,把该点变为树的重心。如果该点可以就输出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
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include  
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair 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 inline void getmax(T1 &a, T2 b) {if (b>a)a = b;}  
template inline void getmin(T1 &a, T2 b) {if (b adj[N]; //邻接矩阵 
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>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 <


你可能感兴趣的:(动态规划—树形dp)