[BZOJ] camino más largo

título

  Haga clic aquí para ver el tema.
   Es la autoridad en el BZOJ tema.

análisis

  Esta pregunta puede ser la regla de puntos, pero al igual que el Qaq tabique lateral.
  proceso de partición, tenemos en cuenta el valor máximo de la ruta por el lado doloroso del divide y vencerás. Un camino a través del lado de la partición se divide en dos lados de la partición (no incluyendo el lado de la partición), sólo necesitamos su período mínimo que se incluirá respuestas.
  Es decir, para cada uno de los bloques de partición de un punto a la ruta en la reciente lado partición punto final, sólo tenemos que calcular su valor mínimo como el valor mínimo de las respuestas de ruta óptima (es decir, puntos de necesidad a través del camino de la Administración de la frontera longitud de la más larga), de modo que ninguna pesada -. Más importante aún, se dice que no se moleste.
  Cuando la aplicación específica, ya que sólo la partición de separación lateral se divide en dos bloques, por lo que la exploración dos triples calculados ordenados respuesta.

código *

#include <cstdio>
#include <vector>
#include <algorithm>
using namespace std;

typedef long long LL;

const int INF = 0x3f3f3f3f;
const int MAXN = 2e5 + 5;

template<typename _T>
void read( _T &x )
{
	x = 0;char s = getchar();int f = 1;
	while( s > '9' || s < '0' ){if( s == '-' ) f = -1; s = getchar();}
	while( s >= '0' && s <= '9' ){x = ( x << 3 ) + ( x << 1 ) + ( s - '0' ), s = getchar();}
	x *= f;
}

template<typename _T>
void write( _T x )
{
	if( x < 0 ){ putchar( '-' ); x = ( ~ x ) + 1; }
	if( 9 < x ){ write( x / 10 ); }
	putchar( x % 10 + '0' );
}

template<typename _T>
_T MAX( const _T a, const _T b )
{
	return a > b ? a : b;
}

template<typename _T>
_T MIN( const _T a, const _T b )
{
	return a < b ? a : b;
}

struct edge
{
	int to, nxt, w;
}Graph[MAXN << 1];

struct node
{
	int mn, len;
	node() { mn = len = 0; }
	node( const int M, const int L ) { mn = M, len = L; }
	bool operator < ( const node & b ) const { return mn > b.mn; }
}t[2][MAXN];

vector<int> G[MAXN];

int mx[MAXN];
int head[MAXN], score[MAXN], siz[MAXN];
LL ans;
int N, tot, l[2], cnt = 1;
bool vis[MAXN];

void addEdge( const int from, const int to, const int W )
{
	Graph[++ cnt].to = to, Graph[cnt].nxt = head[from], Graph[cnt].w = W;
	head[from] = cnt;
}

void addE( const int from, const int to, const int W ) { addEdge( from, to, W ), addEdge( to, from, W ); }

void rebuild( const int u, const int fa )
{
	int cur, lst = 0;
	for( int i = 0, v ; i < G[u].size() ; i ++ )
		if( ( v = G[u][i] ) ^ fa )
		{
			if( ! lst ) addE( lst = u, v, 1 );
			else score[cur = ++ tot] = score[u], addE( lst, cur, 0 ), addE( cur, v, 1 ), lst = cur;
			rebuild( v, u );
		}
}

int getCen( const int u, const int fa, const int all )
{
	int ret = 0, tmp; siz[u] = 1;
	for( int i = head[u], v, id ; i ; i = Graph[i].nxt )
		if( ( v = Graph[i].to ) ^ fa && ! vis[id = ( i >> 1 )] )
		{
			tmp = getCen( v, u, all );
			siz[u] += siz[v];
			mx[id] = MAX( siz[v], all - siz[v] );
			if( mx[id] < mx[ret] ) ret = id;
			if( mx[tmp] < mx[ret] ) ret = tmp;
		}
	return ret;
}

void DFS( const int u, const int fa, const int d, const int val, const int side )
{
	t[side][++ l[side]] = node( val, d );
	for( int i = head[u], v ; i ; i = Graph[i].nxt )
		if( ( v = Graph[i].to ) ^ fa && ! vis[i >> 1] )
			DFS( v, u, d + Graph[i].w, MIN( val, score[v] ), side );
}

void divide( const int x, const int all )
{
	if( all == 1 ) return ;
	int cur = getCen( x, 0, all );
	int fr = Graph[cur << 1].to, to = Graph[cur << 1 | 1].to, w = Graph[cur << 1].w;
	vis[cur] = true;
	l[0] = l[1] = 0;
	DFS( fr, 0, 0, score[fr], 0 );
	DFS( to, 0, 0, score[to], 1 );
	sort( t[0] + 1, t[0] + 1 + l[0] ), sort( t[1] + 1, t[1] + 1 + l[1] );
	int mxl = -INF;
	for( int i = 1, p = 1 ; i <= l[0] ; i ++ )
	{
		for( ; p <= l[1] && t[1][p].mn >= t[0][i].mn ; p ++ ) mxl = MAX( mxl, t[1][p].len );
		ans = MAX( ans, 1ll * t[0][i].mn * ( t[0][i].len + mxl + w + 1 ) );
		ans = MAX( ans, 1ll * t[0][i].mn * ( t[0][i].len + 1 ) );
	}
	mxl = -INF;
	for( int i = 1, p = 1 ; i <= l[1] ; i ++ )
	{
		for( ; p <= l[0] && t[0][p].mn >= t[1][i].mn ; p ++ ) mxl = MAX( mxl, t[0][p].len );
		ans = MAX( ans, 1ll * t[1][i].mn * ( t[1][i].len + mxl + w + 1 ) );
		ans = MAX( ans, 1ll * t[1][i].mn * ( t[1][i].len + 1 ) );
	}
	if( siz[fr] > siz[to] ) siz[fr] = all - siz[to];
	else siz[to] = all - siz[fr];
	divide( fr, siz[fr] ); 
	divide( to, siz[to] );
}

int main()
{
	read( N ); tot = N;
	for( int i = 1 ; i <= N ; i ++ ) read( score[i] );
	for( int i = 1, a, b ; i < N ; i ++ ) read( a ), read( b ), G[a].push_back( b ), G[b].push_back( a );
	rebuild( 1, 0 );
	mx[0] = INF, divide( 1, tot );
	write( ans ), putchar( '\n' );
	return 0;
}

Supongo que te gusta

Origin www.cnblogs.com/crashed/p/12591753.html
Recomendado
Clasificación