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;
}