【Codeforces Round #614(div2)】E-Xenon's Attack on the Gangs(树形dp)

First, the topic Link

https://codeforces.com/contest/1293/problem/E

Second, 题意

To n nodes, n-1 Article undirected edges. That is a tree. We need to give this edge forming the n-1 0 ~ n-2 on the unique values.

mex (u, v) u represents from junction to the maximum non-negative integer edge node weights v passes do not appear.

S is defined as follows:
Here Insert Picture Description

Selecting the maximum value of S.

Third, the data range

2 ≤ n ≤ 3000

1 ≤ in i u_i , v i v_i ≤ n; in i u_i v i v_i

Fourth, the problem-solving ideas

First sample two combined understanding the problem.

Here Insert Picture Description
Here Insert Picture Description
Here Insert Picture Description
For example mex (2,5), through the right side of 3,0,1, the smallest non-negative integer not occurred is 2, so the mex (2,5) = 2.

We found a very crucial point: the sample explanations are omitted mex (1,4), mex (1,2 ), mex (3,5), because its values are 0, the S no contributions. Thus, a path is the S contributes, depending on whether it passes through 0; make much contribution to it, it depends on the number of passes of the longest consecutive non-negative integers . After 0, 1, 2 contribution; after 1, 2, 3 ...... contributions

In other words, it can be calculated S: 0 path through the edge weight, the contribution of +1; 0,1 path through the right side, then the contribution of S + 1 ...... make the maximum, where the continuous non-negative integers to the extent possible side continuous.

Understand this point, we want to make the assignment plan, it may be from "0" to consider. The product of a weight of "0" of the number of nodes on both sides of the edge of the tree to this contribution is "0"; a product of a weight of "0" on both sides of the path of nodes is "1" this contribution tree .

We use this idea recalculate Example: "0" on the left has three nodes (2,4), on the right there are two nodes (3,5), the contribution of 3 × 2 = 6;

"0" on the left has three nodes (2,4), the right there is a node (5), the contribution of 3 × 1 = 3;

"0,1,2" has left a node (4), the right there is a node (5), the contribution of 1 × 1 = 1;

"0,1,2,3" discontinuity in the figure, the contribution of 0.

sum = 6 + 3 + 1 = 10 = S, in line with expectations.

As can be seen, the value of S is acquired by transfer of more inter-cell state, both sides of the common path of nodes determined . We withdrawn from the head end to a tree, i, j, thinking the end of the chain, there are:

S = dp [i] [j] = i * number of nodes on the left to the right of the number of nodes j + max (dp [i, j-1], dp [i + 1, j])

We disassembled the tree into a chain. Due to the discontinuous right side no contribution to S, so every time the calculation of the chain, the other nodes can be ignored. Enumeration chain, dynamic programming, whichever is greater, is the ans.

Five, AC codes

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MAXN = 3005;
vector <int> edge[MAXN];
int n, fa[MAXN][MAXN];
ll ans, cnt[MAXN][MAXN], dp[MAXN][MAXN];

ll solve(int a, int b)
{
    if (a == b) return 0;
    if (dp[a][b] != -1) return dp[a][b];
    return dp[a][b] = cnt[a][b] * cnt[b][a] + max(solve(fa[a][b], a), solve(fa[b][a], b)); //状态转移,fa[a][b]即为从b结点向a结点靠近一点,fa[b][a]同理
}
void search(int root, int k, int dad)
    //dad是以root为根结点情况下,k的父亲
{
    cnt[root][k]++; //以root为根,k子结点的个数。这里是先把k结点计算进去,下面再枚举更新
    fa[root][k] = dad; //更新k的父结点
    for (auto t:edge[k]) //枚举和k相连的边
    {
        if (t != dad) //确保是子结点
        {
            search(root, t, k); //k变成父结点,更新子结点t的状态
            cnt[root][k] += cnt[root][t]; //更新以root为根,k子结点的个数
        }
    }
}
int main()
{
    cin >> n;
    memset(dp, -1, sizeof(dp));
    for (int i = 1; i < n; i++)
    {
        int u, v;
        cin >> u >> v;
        edge[u].push_back(v); //edge记录两个结点的连接情况
        edge[v].push_back(u); //双向赋值
    }
    for (int i = 1; i <= n; i++)
        search(i, i, -1); 
    for (int i = 1; i <= n; i++)
        for (int j = 1; j <= n; j++)
            if (i != j) ans = max(ans, solve(i, j));
    cout << ans;
    return 0;
}

This makes the first semester tree DP, graph theory are really interesting friends! ! ! We have to seize the last holiday to see more, after ooo, ooo ~ have to return to the world of economics in the School of Business ~

Released five original articles · won praise 8 · views 704

Guess you like

Origin blog.csdn.net/weixin_45785492/article/details/104102611