[Planificación dinámica] [Cambiar raíz] Codeforces 1292C El ataque de Xenon contra las pandillas

Asunto

Ahora hay un árbol de \ (n (2 \ leq n \ leq 3000) \) nodos, a cada arista se le asigna un peso entero de \ ([0,2] \) \ (w \) , todas las asignaciones Los enteros de son diferentes, y cada entero puede asignarse a un borde.

Definición: \ (S_ {ruta (s, t)} = mex _ {(u, v) \ en ruta (s, t)} w (u, v) \)
requiere maximización \ (\ sum \ limits_ {1 \ leq s <t \ leq n} S_ {ruta (s, t)} \)

Solución

Teniendo en cuenta la contribución de cada borde, asignamos pesos de borde que comienzan en 0.
Supongamos que hacemos \ (w (u_0, v_0) = 0 \) , dejamos que el borde \ ((u_0, v_0) \) divida el árbol en dos conjuntos de puntos, y el tamaño del conjunto de puntos que contiene \ (u \) es \ (Tamaño (u_0) \) , el tamaño del conjunto de puntos que contiene \ (v_0 \) es \ (Tamaño (v_0) \) . Luego, después de \ (w (u_0, v_0) = 0 \) , para todas las rutas que se cruzan \ ((u_0, v_0) \) , \ (mex \) es mayor que \ (0 \) , la contribución es \ (Tamaño (u_0) \ veces Tamaño (v_0) \) . Luego, vamos a asignar el peso del borde 1, de modo que \ (w (u_1, v_1) = 1 \) , porque es \ (mex \) , por lo que en este momento, solo pasamos por \ ((u_0, v_0) \) y \ (( u_1, v_1) \) han contribuido. Obviamente, \ ((u_1, v_1) \) debe ser lo mismo que \ ((u_0, v_0) \)Conectado es mejor. Por analogía, eventualmente asignaremos pesos de borde a cada borde en una cadena de árbol. A los bordes que no están en esta cadena de árbol no se les asignarán pesos de borde y no contribuirán a la respuesta. Y el poder fronterizo en esta cadena primero debe disminuir y luego aumentar, de lo contrario la respuesta a la prueba no será mejor.

Debido a que los pesos laterales en la cadena disminuyen primero y luego aumentan, cada vez que los pesos laterales se asignan a los dos extremos de la cadena de acuerdo con el peso lateral pequeño. Esto es similar al intervalo dp. Deje que \ (dp [u] [v] \) indique que a la cadena de árbol de árbol \ (u \ sim v \) se le ha asignado la respuesta de borde \ (0 \ sim l-1 \) para obtener la respuesta máxima. Deje que \ (Tamaño_ {raíz} (u) \) represente el tamaño del subárbol enraizado con \ (u \) cuando \ (raíz \) está enraizado , \ (Fa_ {raíz} (u) \) representa \ (root \) es el padre de root \ (u \) . Entonces \ (dp [u] [v] = max (dp [u] [Fa_u (v)], dp [Fa_v (u)] [v]) + Size_u (v) \ veces Size_v (u) \) . Para \ (Size_ {root} (u) \) y \ (Fa_ {root} (u) \) , simplemente ejecute el preprocesamiento DFS desde cada punto. Para \ (dp [u] [v] \ ) Búsqueda de memoria. Complejidad de tiempo \ (O (n ^ 2) \) .

Código

#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <map>
using namespace std;

#define RG register int
#define LL long long

template<typename elemType>
inline void Read(elemType &T){
    elemType X=0,w=0; char ch=0;
    while(!isdigit(ch)) {w|=ch=='-';ch=getchar();}
    while(isdigit(ch)) X=(X<<3)+(X<<1)+(ch^48),ch=getchar();
    T=(w?-X:X);
}

struct edge{int Next,to;};
edge G[6010];
int head[3010],Fa[3010][3010];
LL Size[3010][3010],dp[3010][3010];
int N,cnt=2;
LL Ans=0;

inline void Add_Edge(int u,int v){
    G[cnt].to=v;
    G[cnt].Next=head[u];
    head[u]=cnt++;
}

void DFS(int u,int fa,int root){
    Size[root][u]=1;
    for(int i=head[u];i;i=G[i].Next){
        int v=G[i].to;
        if(v==fa) continue;
        Fa[root][v]=u;
        DFS(v,u,root);
        Size[root][u]+=Size[root][v];
    }
    return;
}

LL DP(int u,int v){
    if(u==v) return 0;
    if(dp[u][v]) return dp[u][v];
    return dp[u][v]=max(DP(u,Fa[u][v]),DP(Fa[v][u],v))+Size[u][v]*Size[v][u];
}

int main(){
    Read(N);
    for(RG i=1;i<=N-1;++i){
        int u,v;
        Read(u);Read(v);
        Add_Edge(u,v);
        Add_Edge(v,u);
    }
    for(RG i=1;i<=N;++i)
        DFS(i,0,i);
    for(RG u=1;u<=N;++u)
        for(RG v=1;v<=N;++v)
            Ans=max(Ans,DP(u,v));
    printf("%I64d\n",Ans);
    return 0;
}

Supongo que te gusta

Origin www.cnblogs.com/AEMShana/p/12695375.html
Recomendado
Clasificación