E. Arbre Peinture (dp + arbre de changement de racine)

titre

Signification des questions:

    Compte tenu d'un arbre, le point de départ est un blanc, un tachée chaque fois que vous pouvez pointer fraction est obtenue qui ne contient que le nombre de points de blocs de communication de point blanc dans le point de rattachement actuel. Sortie jusqu'à score.
     2 n 2 1 0 5 2≤n≤2⋅10 ^ 5

analyse:

    Chaque fois qu'un des opérations ponctuelles sera divisé en sous - arbres arbre m, et nous nœud parent certainement la première exploitation, puis manipuler les nœuds enfants, pensez donc naturellement d'un dp d'arbre. Mais nous ne savons pas la racine, il sera effectué pour changer la racine.
    Arbre dp, dp [i] i est exprimée dans le sous - arbre enraciné à la valeur maximale obtenue dans l'opération, dp [i] = dp [ t] + fils [i] (t i du nœud enfant, fils [i] est Le secteur de la section de petits - i). Transfert au changement de racine dp [t] = dp [i ] - fils [t] + fils [i] - fils [t], le score actuel du noeud parent de ce noeud est maintenant à soustraire les petits - enfants de racine d' origine noeuds, ainsi que maintenant la contribution originale du noeud parent de t. Notez que cette fois la racine a changé, nous devons changer la valeur du fils [t], puis revenir quand faire marche arrière.

#include <iostream>
#include <vector> 
using namespace std;

typedef long long ll;

int son[200005];
ll dp[200005];
vector<int> g[200005]; 

void dfs1(int x,int fa)
{
	if( g[x].size() == 1 && g[x][0] == fa )
	{
		son[x] = 1;
		dp[x] = 1;
		return;
	}
	for (int i = 0; i < g[x].size(); i++)
	{
		int t = g[x][i];
		if( t == fa ) continue;
		dfs1(t,x);
		son[x] += son[t];
		dp[x] += dp[t];
	}
	son[x] ++;
	dp[x] += son[x];
}

void dfs2(int x,int fa)
{
	for (int i = 0; i < g[x].size(); i++)
	{
		int t = g[x][i];
		if( t == fa ) continue;
		int gap = son[x] - son[t];
		dp[t] = dp[x] - son[t] + gap;
		son[t] += gap;
		dfs2(t,x);
		son[t] -= gap;
	}
}

int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0);
	int n;
	cin >> n;
	for (int i = 1; i < n; i++)
	{
		int x,y;
		cin >> x >> y;
		g[x].push_back(y);
		g[y].push_back(x);
	}
	dfs1(1,0);
	dfs2(1,0);
	ll ans = 0;
	for (int i = 1; i <= n; i++)
	{
		//cout << i << ' ' << dp2[i] << '\n';
		ans = max(ans,dp[i]); 
	}
	cout << ans << '\n';
	return 0;
}

Publié 132 articles originaux · a gagné les éloges 6 · vues 7912

Je suppose que tu aimes

Origine blog.csdn.net/weixin_44316314/article/details/105096598
conseillé
Classement