Codeforces Round #614 (Div. 2)E(思维,构造,DP)

构造边权,从0开始给边赋值,初始选取一条边权为0,每次赋值的贡献为这一条链两侧的结点(包含链的端点)个数之积,下一次赋值以当前链其一端点续一条边,边权为上次赋的值+1。先DFS找到点的组合这条链两侧结点的个数(包含链的端点),然后枚举端点进行DP。

 1 #define HAVE_STRUCT_TIMESPEC
 2 #include<bits/stdc++.h>
 3 using namespace std;
 4 vector<long long>edge[3007];
 5 long long cnt[3007][3007];
 6 long long fa[3007][3007];
 7 long long dp[3007][3007];
 8 void dfs(long long now,long long f,long long root){
 9     cnt[root][now]=1;//链的起点与当前点相反的一侧的结点个数(包括链的端点)
10     fa[root][now]=f;//当前点与链的起点相同的一侧的父节点为f
11     for(auto it:edge[now]){
12         if(it==f)
13             continue;
14         dfs(it,now,root);
15         cnt[root][now]+=cnt[root][it];//将结果回溯到上层结点
16     }
17 }
18 long long solve(long long l,long long r){//求以l和r作为链的端点的答案最大值
19     if(l==r)//起点与终点不能相同
20         return 0;
21     if(dp[l][r]==0)//l和r第一次作为链的两端
22         dp[l][r]=cnt[l][r]*cnt[r][l]+max(solve(l,fa[l][r]),solve(r,fa[r][l]));//这一段的结果为链两端结点个数(包括链的段点)乘积加上当前链去掉一个端点的答案(两个端点其一为新加入的点,新边的权值为原链中边的权值最大值+1)
23     return dp[l][r];
24 }
25 int main(){
26     ios::sync_with_stdio(false);
27     cin.tie(NULL);
28     cout.tie(NULL);
29     long long n;
30     cin>>n;
31     for(long long i=1;i<n;++i){
32         long long u,v;
33         cin>>u>>v;
34         edge[u].emplace_back(v);
35         edge[v].emplace_back(u);
36     }
37     for(long long i=1;i<=n;++i)//枚举链的起点
38         dfs(i,-1,i);//深搜
39     long long ans=0;
40     for(long long i=1;i<=n;++i)//枚举链的起点
41         for(long long j=1;j<=n;++j)//枚举链的终点
42             ans=max(ans,solve(i,j));
43     cout<<ans;
44     return 0;
45 }

 

posted @ 2020-01-25 22:57  sewage  阅读(148)  评论(0编辑  收藏  举报