CF 70 E 题解
程序员文章站
2022-07-07 08:32:38
dpi,jdp_{i,j}dpi,j表示距离i最近的标记点为j。那么:dpi,j={...+k(i=j)...+ddisi,j(i≠j)dp_{i,j}=\left\{\begin{matrix} ...+k(i=j) \\ ...+d_{dis_{i,j}}(i\neq j)\end{matrix}\right.dpi,j={...+k(i=j)...+ddisi,j(i=j)那么这个省略号里面是什么呢?我们只知道是转移到子树的dp。我们可以分情况讨论:如果depth(i)...
表示距离i最近的标记点为j。那么:
那么这个省略号里面是什么呢?我们只知道是转移到子树的dp。
我们可以分情况讨论:
如果的时候则对于儿子u的转移如下:
但是其实隐藏了一个条件就是:,不过这种情况会被所覆盖,答案会更优所以就没关系了。
接下来考虑的情况:
其实这个东西是可以预处理的,所以总的复杂度是的,这题的n其实可以出到。
输出路径的话其实只需要跑一个和原来一样的记忆话搜索就ok了。
code:
/*
{
AuThOr Gwj
*/
#pragma GCC optimize(2)
#include<bits/stdc++.h>
#define rb(a,b,c) for(int a=b;a<=c;++a)
#define rl(a,b,c) for(int a=b;a>=c;--a)
#define LL long long
#define IT iterator
#define PB push_back
#define II(a,b) make_pair(a,b)
#define FIR first
#define SEC second
#define FREO freopen("check.out","w",stdout)
#define rep(a,b) for(int a=0;a<b;++a)
#define SRAND mt19937 rng(chrono::steady_clock::now().time_since_epoch().count())
#define random(a) rng()%a
#define ALL(a) a.begin(),a.end()
#define POB pop_back
#define ff fflush(stdout)
#define fastio ios::sync_with_stdio(false)
#define R(a) cin>>a
#define R2(a,b) cin>>a>>b
using namespace std;
const int INF=0x3f3f3f3f;
typedef pair<int,int> mp;
/*}
*/
int n,k;
const int MAXN=180+2;
int dp2[MAXN],dp[MAXN][MAXN],d[MAXN],depth[MAXN],dis[MAXN][MAXN];
bool vis[MAXN][MAXN];
vector<int> g[MAXN];
int dfs(int now,int best,int pre=0){
if(vis[now][best]){
return dp[now][best];
}
vis[now][best]=1;
if(best==now){
dp[now][best]=k;
}
else{
dp[now][best]=d[dis[now][best]];
}
for(auto it:g[now]){
if(it==pre) continue;
if(dis[it][best]+1==dis[now][best]) continue;
dp[now][best]+=min(dfs(it,best,now),dp2[it]);
}
for(auto it:g[now]){
//cout<<now<<" "<<best<<" "<<it<<" "<<dis[it][best]<<" "<<dis[now][best]<<" "<<pre<<endl;
if(it==pre) continue;
if(dis[it][best]+1==dis[now][best]){
// cout<<now<<"Yes"<<best<<" "<<it<<endl;
dp[now][best]+=dfs(it,best,now);
}
}
return dp[now][best];
}
int run(int st,int now,int pre=0){
// cout<<<<now<<"~"<<pre<<endl;
int res=dfs(st,now,pre);
for(auto it:g[now]){
if(depth[it]>depth[now])
res=min(res,run(st,it,pre));
}
return res;
}
void init(int now,int pre=0){
depth[now]=depth[pre]+1;
for(auto it:g[now]){
if(it==pre) continue;
init(it,now);
}
}
void dfs_dis(int st,int now,int pre=0,int dist=0){
dis[st][now]=dist;
for(auto it:g[now]){
if(it==pre) continue;
dfs_dis(st,it,now,dist+1);
}
}
void dfs_help(int now,int pre=0){
for(auto it:g[now]){
if(it==pre) continue;
dfs_help(it,now);
}
dp2[now]=run(now,now,pre);
}
int rest[MAXN];
int print2(int now,int pre){
rb(i,1,n){
if(depth[i]>=depth[now]&&dis[i][now]==depth[i]-depth[now]&&dp2[now]==dfs(now,i,pre)){
return i;
}
}
assert(0);
return now;//That's impossible
}
void print(int now,int best,int pre){
rest[now]=best;
for(auto it:g[now]){
if(it==pre) continue;
if(dis[it][best]+1==dis[now][best]) continue;
if(dfs(it,best,now)<dp2[it]){
print(it,best,now);
}
else{
print(it,print2(it,now),now);
}
}
for(auto it:g[now]){
if(it==pre) continue;
if(dis[it][best]+1==dis[now][best]){
print(it,best,now);
break;
}
}
}
int main(){
fastio;
R2(n,k);
rb(i,1,n-1){
R(d[i]);
}
rb(i,2,n){
int u,v;
R2(u,v);
g[u].PB(v);
g[v].PB(u);
}
memset(dp2,63,sizeof(dp2));
init(1);
rb(i,1,n)
dfs_dis(i,i);
dfs_help(1);
int res=INF;
rb(i,1,n)
{
res=min(dfs(1,i),res);
}
cout<<res<<endl;
rb(i,1,n){
if(dfs(1,i)==res){
print(1,i,0);
break;
}
}
rb(i,1,n){
cout<<rest[i]<<" ";
}cout<<endl;
return 0;
}
本文地址:https://blog.csdn.net/qq_42925924/article/details/107889500
下一篇: 千万别被卖家秀给骗了!
推荐阅读
-
Galaxy A70e渲染图曝光:边框感人 MicroUSB充电口
-
cf1060E. Sergey and Subway(思维 枚举)
-
【题解】CF161B Discounts
-
Linux使用vim编辑文件保存时报E514:write error (file system full?)问题解决
-
cf932E. Team Work(第二类斯特灵数 组合数)
-
【题解】 CF1284A New Year and Naming
-
CF341E Candies Game
-
事件函数function(e){}中e的问题解决办法
-
cf1130E. Wrong Answer(构造)
-
【问题解决】vim 打开文档后提醒 E325: ATTENTION 怎么办?