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 }
保持热爱 不懈努力
不试试看怎么知道会失败呢(划掉)
世上无难事 只要肯放弃(划掉)