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