CF1292C Xenon's Attack on the Gangs 题解
Posted liuchanglc
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CF1292C Xenon's Attack on the Gangs 题解相关的知识,希望对你有一定的参考价值。
题目描述
输入格式
输出格式
题意翻译
给n
个结点,n-1
条无向边。即一棵树。我们需要给这n-1
条边赋上0~ n-2
不重复的值。mex(u,v)
表示从结点u
到结点v
经过的边权值中没有出现的最小非负整数。计算下面等式的最大值:
样例
样例输入
3 1 2 2 3
5 1 2 1 3 1 4 3 5
样例输出
样例输出一
3
样例输出二
10
分析
我们先随便找一条边,将它的价值赋值成0
那么只要有一个路径经过这条边,那么这个路径的最小价值就一定不会为0
我们举一个例子
此时u到v的价值为1,那么这一条路径不经过的最小非负整数就是0
除了这一条路径以外,其他的路径只要经过(u,v)这条边,那么它们不经过的最小非负整数都为1(因为它们已经经过了0)
我们用f[i][j]表示从i开始,从j结束,将i到j之间所有的m条边赋值成0到m-1所得到的最大价值
用g[i][j]表示在i号节点作为根节点的情况下,以j为根节点的字数的大小
用pa[i][j]表示在i号节点作为根节点的情况下,j节点的父亲节点
我们再来看上面这幅图,除了(u,v)这条边之外,只要经过(u,v)这条边,那么它们没有经过的最小非负整数的价值就为
此时总价值为g[u][v]*g[v][u]
那么我们再添加价值为1的边,为了使总的价值最大,这条边显然要和价值为0的边放在一起
为什么呢?因为如果放在别的地方,那么价值为1的路程会增多,而价值为2的路程会减少
换一句话说,价值为1的这条边对其它路程的贡献减少了
我们来举一个例子
在左边这幅图中,我们没有把价值为1的边放在价值为0的边的旁边,这时(u,B)这条边永远会缺失1,我们从v向下遍历,同时经过0和1的路径的个数会减少,会有很多路径的价值为1,以后也不会再改变
在右边这幅图中,我们有把价值为1的边放在价值为0的边的旁边,这时(u,B)这条边的边权1,它的价值也就为1,我们从v向下遍历,同时经过0和1的路径的个数显然要比上面的多,路径的价值一定会大于1
总而言之,我们应该把价值为1的边放在 u 或 v 的邻边上,不然同时经过 0,1 的路径肯定会少,对答案能贡献 2 的路径也会变少,并且接下来填 2 能获得的贡献也不会多
同样的,我们可以把2 、3、4……n-1依次填入,只要按照上面的方法就可以
但是还有一个问题,我们是从左边加还是从右边加呢
这是我们就需要用到动态转移方程取较大值
什么意思呢,我们还是拿图来说
我们假设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否则会爆掉
代码
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #include<iostream> 5 #include<cmath> 6 using namespace std; 7 const int maxd=3010; 8 typedef long long ll; 9 struct asd{ 10 ll from,to,next; 11 }b[maxd*2]; 12 ll head[maxd],tot=1; 13 void ad(ll aa,ll bb){ 14 b[tot].from=aa; 15 b[tot].to=bb; 16 b[tot].next=head[aa]; 17 head[aa]=tot++; 18 } 19 ll pa[maxd][maxd],f[maxd][maxd],g[maxd][maxd]; 20 ll rt=1; 21 void dfs(ll now,ll fa){ 22 g[rt][now]=1; 23 for(ll i=head[now];i!=-1;i=b[i].next){ 24 ll u=b[i].to; 25 if(u==fa) continue; 26 pa[rt][u]=now; 27 dfs(u,now); 28 g[rt][now]+=g[rt][u]; 29 } 30 } 31 ll solve(ll u,ll v){ 32 if(u==v) return 0; 33 if(f[u][v]) return f[u][v]; 34 return f[u][v]=max(solve(u,pa[u][v]),solve(v,pa[v][u]))+g[u][v]*g[v][u]; 35 } 36 int main(){ 37 memset(head,-1,sizeof(head)); 38 ll n; 39 scanf("%lld",&n); 40 for(ll i=1;i<n;i++){ 41 ll aa,bb; 42 scanf("%lld%lld",&aa,&bb); 43 ad(aa,bb); 44 ad(bb,aa); 45 } 46 for(ll i=1;i<=n;i++){ 47 rt=i; 48 dfs(i,-1);//递归,预处理s数组和pa数组 49 } 50 ll ans=-1; 51 for(ll i=1;i<=n;i++){ 52 for(ll j=1;j<=n;j++){ 53 ans=max(solve(i,j),ans);//取最大值 54 } 55 } 56 printf("%lld ",ans); 57 return 0; 58 }
以上是关于CF1292C Xenon's Attack on the Gangs 题解的主要内容,如果未能解决你的问题,请参考以下文章
CodeForces 1292C Xenon's Attack on the Gangs
cf1293EE.Xenon's Attack on the Gangs(dp)
CF1293E-Xenon's Attack on the Gangs 树状DP
Codeforces Round #614 (Div. 2) E. Xenon's Attack on the Gangs
Codeforces Round #614 (Div. 2) E. Xenon's Attack on the Gangs