换根dp+暴力+预处理+记忆化搜索——cf1292C好题!

/**
给定一棵树,要求给树边赋值[0,n-2],每个值只能使用一次
    S = mex(u,v), mex(u,v)是u-v路径上没有出现过的编号最小的值
    问使得S最大的赋值方式 

由于很难直接统计答案,所以考虑统计每条边的贡献
    包含(0)路径的贡献tot1是其左右子树size的乘积
    包含(0,1)的路径的贡献tot2是其左右子树的size乘积
    ...依次类推
    显然:只包含(1,2)这样的路径是没有贡献的

那么原问题转化为如何分配[0,n-2],使得最后的乘积和最大
dp[u][v]表示路径(u,v)的贡献 ,O(n^2)的时间内求完即可
    显然root不同,答案也会不同,所以先预处理出
        size[root][u],表示以root为根时u的儿子大小
         fa[root][u],表示以root为根时u的父亲
    两重循环+记忆化搜索求出所有dp[u][v]
*/
#include<bits/stdc++.h>
using namespace std;
#define N 3005
#define ll long long 

vector<int>G[N];
ll n,dp[N][N],size[N][N],fa[N][N];

void dfs(int u,int pre,int root){
    size[root][u]=1;fa[root][u]=pre;
    for(auto v:G[u]){
        if(v==pre)continue;
        dfs(v,u,root);
        size[root][u]+=size[root][v];
    }
}
ll solve(int u,int v){
    if(u==v)return 0;
    if(dp[u][v]!=-1)return dp[u][v];
    dp[u][v]=size[u][v]*size[v][u]
        +max(solve(u,fa[u][v]),solve(v,fa[v][u]));
    return dp[u][v];
}

int main(){
    cin>>n;
    for(int i=1;i<n;i++){
        int u,v;
        cin>>u>>v;
        G[u].push_back(v);
        G[v].push_back(u);
    }

    for(int root=1;root<=n;root++)
        dfs(root,0,root);

    memset(dp,-1,sizeof dp);
    ll ans=0;
    for(int u=1;u<=n;u++)
        for(int v=1;v<=n;v++)
            ans=max(ans,solve(u,v));
    cout<<ans<<‘\n‘;
}
 

原文地址:https://www.cnblogs.com/zsben991126/p/12264140.html

时间: 2024-08-09 00:46:59

换根dp+暴力+预处理+记忆化搜索——cf1292C好题!的相关文章

hdu4753 状态压缩dp博弈(记忆化搜索写法)

http://acm.hdu.edu.cn/showproblem.php?pid=4753 Problem Description There is a 3 by 3 grid and each vertex is assigned a number. It looks like JiuGongGe, but they are different, for we are not going to fill the cell but the edge. For instance, adding

NYOJ16|嵌套矩形|DP|DAG模型|记忆化搜索

矩形嵌套 时间限制:3000 ms  |  内存限制:65535 KB 难度:4 描述 有n个矩形,每个矩形可以用a,b来描述,表示长和宽.矩形X(a,b)可以嵌套在矩形Y(c,d)中当且仅当a<c,b<d或者b<c,a<d(相当于旋转X90度).例如(1,5)可以嵌套在(6,2)内,但不能嵌套在(3,4)中.你的任务是选出尽可能多的矩形排成一行,使得除最后一个外,每一个矩形都可以嵌套在下一个矩形内. 输入 第一行是一个正正数N(0<N<10),表示测试数据组数,每组测

ACM学习历程—ZOJ3471 Most Powerful(dp &amp;&amp; 状态压缩 &amp;&amp; 记忆化搜索 &amp;&amp; 位运算)

Description Recently, researchers on Mars have discovered N powerful atoms. All of them are different. These atoms have some properties. When two of these atoms collide, one of them disappears and a lot of power is produced. Researchers know the way

poj 1609 Tiling Up Blocks dp入门之记忆化搜索

题意: 给n个二元组(a,b),要在其中找最长的序列,使得对序列中的任意i<j,有ai<=aj且bi<=bj. 分析: 设dp[a][b]代表以(a,b)结尾的最长序列长度,记忆化搜索即可. 代码: //poj 1609 //sep9 #include <iostream> using namespace std; const int max_p=128; int n; int num[max_p][max_p]; int dp[max_p][max_p]; int sear

poj1191 棋盘分割【区间DP】【记忆化搜索】

棋盘分割 Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 16263   Accepted: 5812 Description 将一个8*8的棋盘进行如下分割:将原棋盘割下一块矩形棋盘并使剩下部分也是矩形,再将剩下的部分继续如此分割,这样割了(n-1)次后,连同最后剩下的矩形棋盘共有n块矩形棋盘.(每次切割都只能沿着棋盘格子的边进行) 原棋盘上每一格有一个分值,一块矩形棋盘的总分为其所含各格分值之和.现在需要把棋盘按上述规

【区间dp】【记忆化搜索】UVALive - 3516 - Exploring Pyramids

f(i,j)=sum(f(i+1,k-1)*f(k,j) | i+2<=k<=j,Si=Sk=Sj). f(i+1,k-1)是划分出第一颗子树,f(k,j)是划分出剩下的子树. #include<cstdio> #include<cstring> using namespace std; typedef long long ll; #define MOD 1000000000ll char s[310]; ll f[310][310]; int n; ll dp(int

UVa 10651 Pebble Solitaire (DP 卵石游戏 记忆化搜索)

 题意  给你一个长度为12的字符串  由字符'-'和字符'o'组成  其中"-oo"和"oo-"分别可以通过一次转换变为"o--"和"--o"  可以发现每次转换o都少了一个  只需求出给你的字符串做多能转换多少次就行了 令d[s]表示字符串s最多可以转换的次数  若s可以通过一次转换变为字符串t  有d[s]=max(d[s],d[t]+1) #include<iostream> #include<s

HDU 1078 记忆化搜索

FatMouse and Cheese Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 4575 Accepted Submission(s): 1829 Problem Description FatMouse has stored some cheese in a city. The city can be considered as a

Luogu P3953 逛公园(最短路+记忆化搜索)

P3953 逛公园 题面 题目描述 策策同学特别喜欢逛公园.公园可以看成一张 \(N\) 个点 \(M\) 条边构成的有向图,且没有自环和重边.其中 \(1\) 号点是公园的入口,\(N\) 号点是公园的出口,每条边有一个非负权值, 代表策策经过这条边所要花的时间. 策策每天都会去逛公园,他总是从 \(1\) 号点进去,从 \(N\) 号点出来. 策策喜欢新鲜的事物,它不希望有两天逛公园的路线完全一样,同时策策还是一个 特别热爱学习的好孩子,它不希望每天在逛公园这件事上花费太多的时间.如果 \(