CF1292C Xenon's Attack on the Gangs

题目

Input

The first line contains an integer n (2≤n≤3000), the number of gangs in the network.

Each of the next n−1 lines contains integers ui and vi (1≤ui,vi≤n; ui≠vi), indicating there's a direct link between gangs ui and vi.

It's guaranteed that links are placed in such a way that each pair of gangs will be connected by exactly one simple path.

output

Print the maximum possible value of S — the number of password layers in the gangs' network.

Examples

Input

3
1 2
2 3

Output

3

Input

5
1 2
1 3
1 4
3 5

Output

10

Note

题意

给n个结点,n-1条无向边。即一棵树。我们需要给这n-1条边赋上0~ n-2不重复的值。mex(u,v)表示从结点u到结点v经过的边权值中没有出现的最小非负整数。计算下面等式的最大值

 

分析

 根据上式,可以得出一个结论,即只要考虑每条边的贡献就行,每条边要有贡献。

假设求1-2-3-4这样的链的结果,那么假如我们已经知道了它的子结果,1-2-3和2-3-4的结果,我们要从这个结果推出1-2-3-4结果,那么根据我们的分析,从1-2-3和2-3-4变成1-2-3-4都是加上1-2-3-4这条链两头点的乘积(就是这棵树中有多少条链能够覆盖这条链,他们都能得到这个加成),既然加的数值一样,那么肯定选他们两个中大的那个啦。数量的话很简单,对于x-…-y这条链来说,x那边的点的个数就是以y为根,x为子树顶点的子树的点数量,另一边就正好相反,就是刚才说的num[root][u] num[root][u]num[root][u]可以得到,而1-2-3和2-3-4的获得,就可以用fa[root][u] fa[root][u]fa[root][u],同样对于x-…-y这条链来说,fa[x][y] fa[x][y]fa[x][y]就是x-…-y这条链中,与y直接相连的那个点。

代码

#include<cstdio>
#include<cstring>
#include<vector>
#include<stack>
#include<algorithm>
#include<iostream>
using namespace std;
#define ll long long
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define per(i,a,b) for(int i=a;i>=b;i--)
#define inf 0x3f3f3f3f
const int MAXN = 3e3+5;
vector<int>v[MAXN];
ll fa[MAXN][MAXN],num[MAXN][MAXN],dp[MAXN][MAXN],root;
void dfs(int u,int f){
    num[root][u]=1;
    int len=v[u].size();
    rep(i,0,len-1){
        int y=v[u][i];
        if(y==f)continue;
        fa[root][y]=u;
        dfs(y,u);
        num[root][u]+=num[root][y];
    }
}
ll solve(int x,int y){
    if(x==y)return 0;
    if(dp[x][y])return dp[x][y];
    return dp[x][y]=num[x][y]*num[y][x]+max(solve(x,fa[x][y]),solve(y,fa[y][x]));
}
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    int n,x,y;
    while(cin>>n){
        rep(i,1,n)v[i].clear();
        memset(fa,0,sizeof(fa));
        memset(num,0,sizeof(num));
        memset(dp,0,sizeof(dp));
        rep(i,1,n-1){
            cin>>x>>y;
            v[x].push_back(y);
            v[y].push_back(x);
        }
        rep(i,1,n){
            root=i;
            dfs(i,-1);
        }
        ll ans=0;
        rep(i,1,n){
            rep(j,i+1,n){
                ans=max(ans,solve(i,j));
            }
        }
        cout<<ans<<endl;
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/Vocanda/p/12679570.html
今日推荐