[Dynamic Planning] [Change Root] Codeforces 1292C Xenon's Attack on the Gangs

Subject

There is now a tree of \ (n (2 \ leq n \ leq 3000) \) nodes, each edge is assigned an integer weight of \ ([0,2] \) \ (w \) , all allocations The integers of are different, and each integer can be assigned to an edge.

Definition: \ (S_ {path (s, t)} = mex _ {(u, v) \ in path (s, t)} w (u, v) \)
requires maximization \ (\ sum \ limits_ {1 \ leq s <t \ leq n} S_ {path (s, t)} \)

answer

Considering the contribution of each edge, we assign edge weights starting at 0.
Suppose we make \ (w (u_0, v_0) = 0 \) , let edge \ ((u_0, v_0) \) divide the tree into two point sets, and the size of the point set containing \ (u \) is \ (Size (u_0) \) , the size of the point set containing \ (v_0 \) is \ (Size (v_0) \) . Then after \ (w (u_0, v_0) = 0 \) , for all paths that cross \ ((u_0, v_0) \) , \ (mex \) is greater than \ (0 \) , and the contribution is \ (Size (u_0) \ times Size (v_0) \) . Then we go to assign the edge weight 1, so that \ (w (u_1, v_1) = 1 \) , because it is \ (mex \) , so at this time, only pass through \ ((u_0, v_0) \) and \ (( u_1, v_1) \) have contributed. Obviously, \ ((u_1, v_1) \) should be the same as \ ((u_0, v_0) \)Connected is better. By analogy, we will eventually assign edge weights to each edge in a tree chain. Edges that are not in this tree chain will not be assigned edge weights and will not contribute to the answer. And the border power on this chain must first decrease and then increase, otherwise the answer to the proof will not be better.

Because the side weights on the chain decrease first and then increase, each time the side weights are assigned to the two ends of the chain according to the small side weight. This is similar to the interval dp. Let \ (dp [u] [v] \) indicate that the tree tree chain \ (u \ sim v \) has been assigned the edge answer \ (0 \ sim l-1 \) to obtain the maximum answer. Let \ (Size_ {root} (u) \) represent the size of the subtree rooted with \ (u \) when \ (root \) is rooted , \ (Fa_ {root} (u) \) represents \ (root \) is the father of root \ (u \) . Then \ (dp [u] [v] = max (dp [u] [Fa_u (v)], dp [Fa_v (u)] [v]) + Size_u (v) \ times Size_v (u) \) . For \ (Size_ {root} (u) \) and \ (Fa_ {root} (u) \) , just run DFS preprocessing from each point. For \ (dp [u] [v] \ ) Memory search. Time complexity \ (O (n ^ 2) \) .

Code

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

Guess you like

Origin www.cnblogs.com/AEMShana/p/12695375.html