来看一下题目链接:https://www.cnblogs.com/liuchanglc/p/12677786.html
大家在看题解前一定要先看题目哟。
下面我就要开始咯!
题意:给n
个结点,n-1
条无向边。即一棵树。我们需要给这n-1
条边赋上0~ n-2
不重复的值。mex(u,v)
表示从结点u
到结点v
经过的边权值中没有出现的最小非负整数。计算下面等式的最大值:
先来几个定义:
我们用f[i][j]表示从i开始,从j结束,将i到j之间所有的m条边赋值成0到m-1所得到的最大价值
用g[i][j]表示在i号节点作为根节点的情况下,以j为根节点的字数的大小
用pa[i][j]表示在i号节点作为根节点的情况下,j节点的父亲节点。
然后再来张图。
下面给出状态转移方程。
f[u][v]=max(f[u,pa[u][v]],f[v,pa[v][u]])+g[u][v]*g[v][u]
什么意思呢,我们还是拿图来说
我们假设pa[v][u]和pa[u][v]之间的权值已经确定,那么下一个权值我们可以选择加在(u,pa[v][u])上,也可以选择加在(v,pa[u][v])上
如果加在(u,pa[v][u])上,那么增大的价值就是g[u][v]*g[v][u],还要加上原来就有的f[u,pa[u][v]]
如果加在(v,pa[u][v])上,那么增大的价值就是g[u][v]*g[v][u],还要加上原来就有的f[v,pa[v][u]]
实际上这两种情况增大的价值都是一样的,我们只需要在f[u,pa[u][v]]和f[v,pa[v][u]]中取最大值就可以了
g、pa数组我们可以预处理得到,f数组我们枚举取最大值就可以了
这道题也要开long long否则会爆掉
注:图片引用自https://www.cnblogs.com/liuchanglc/ 的博客
下面是代码:
呵呵,再往下看看
先看完整版:
我精简过的,只有38行。
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int maxn=3005; 4 typedef long long ll; 5 struct node{ 6 ll from,to,next; 7 }e[maxn*2];ll head[maxn],cnt=1; 8 void add(ll xx,ll yy){ 9 e[cnt].from=xx;e[cnt].to=yy;e[cnt].next=head[xx];head[xx]=cnt++; 10 } 11 ll pa[maxn][maxn],f[maxn][maxn],g[maxn][maxn],root=1; 12 void DFS(ll now,ll fa){ 13 g[root][now]=1; 14 for(ll i=head[now];i!=-1;i=e[i].next){ 15 ll u=e[i].to;if(u==fa) continue; 16 pa[root][u]=now;DFS(u,now); 17 g[root][now]+=g[root][u]; 18 } 19 } 20 ll jiejue(ll u,ll v){ 21 if(u==v) return 0;if(f[u][v]) return f[u][v]; 22 return f[u][v]=max(jiejue(u,pa[u][v]),jiejue(v,pa[v][u]))+g[u][v]*g[v][u]; 23 } 24 int main(){ 25 //freopen("a.in","r",stdin); 26 ll n;scanf("%lld",&n); 27 memset(head,-1,sizeof(head)); 28 for(ll i=1;i<n;i++){ 29 ll xx,yy;scanf("%lld%lld",&xx,&yy); 30 add(xx,yy);add(yy,xx); 31 } 32 for(ll i=1;i<=n;i++){ 33 root=i;DFS(i,-1); 34 }ll answer=-1; 35 for(ll i=1;i<=n;i++)for(ll j=1;j<=n;j++)answer=max(jiejue(i,j),answer); 36 printf("%lld\n",answer); 37 return 0; 38 }
然后是DFS代码
1 void DFS(ll now,ll fa){ 2 g[root][now]=1; 3 for(ll i=head[now];i!=-1;i=e[i].next){ 4 ll u=e[i].to; 5 if(u==fa) continue; 6 pa[root][u]=now;DFS(u,now); 7 g[root][now]+=g[root][u]; 8 } 9 }
最后是解决部分的代码
1 ll jiejue(ll u,ll v){ 2 if(u==v) return 0; 3 if(f[u][v]) return f[u][v]; 4 return f[u][v]=max(jiejue(u,pa[u][v]),jiejue(v,pa[v][u]))+g[u][v]*g[v][u]; 5 }
这道题主要在于思路吧。