【题解】CF 70E Information Reform
设 \(f_{u,i}\) 表示 \(u\) 接受 \(i\) 的信号,\(u\) 的子树内的答案。那么可以枚举 \(u\) 的儿子 \(v\) 接受信号的节点来转移。注意当 \(v\) 也枚举到 \(i\) 时要减去重复的 \(k\)。
考虑构造方案,设 \(ans_u\) 表示答案。首先可以求出 \(ans_1\)。对于 \(u\) 的每个儿子 \(v\),计算 \(u\) 是怎么从 \(v\) 转移来的即可。仍然注意当 \(v\) 枚举到 \(ans_u\) 时要减去重复的 \(k\)。
用 Floyd 计算两两之间的距离,时间复杂度 \(O(n^3)\)。
复制代码
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
using namespace std;
namespace asbt{
namespace cplx{bool begin;}
const int maxn=205,inf=0x3f3f3f3f3f3f3f3f;
int n,m,a[maxn],ans[maxn];
int dis[maxn][maxn];
int f[maxn][maxn];
vector<int> e[maxn];
il void dfs1(int u,int fa){
for(int i=1;i<=n;i++){
f[u][i]=a[dis[u][i]]+m;
}
for(int v:e[u]){
if(v==fa){
continue;
}
dfs1(v,u);
for(int i=1,tmp;i<=n;i++){
tmp=f[u][i];
f[u][i]+=f[v][i]-m;
for(int j=1;j<=n;j++){
f[u][i]=min(f[u][i],tmp+f[v][j]);
}
}
}
}
il void dfs2(int u,int fa){
for(int v:e[u]){
if(v==fa){
continue;
}
int res=inf;
for(int i=1;i<=n;i++){
if(res>f[v][i]){
res=f[v][i],ans[v]=i;
}
}
if(f[v][ans[u]]-m<f[v][ans[v]]){
ans[v]=ans[u];
}
dfs2(v,u);
}
}
namespace cplx{
bool end;
il double usdmem(){return (&begin-&end)/1048576.0;}
}
signed main(){
ios::sync_with_stdio(0),cin.tie(0);
cin>>n>>m;
for(int i=1;i<n;i++){
cin>>a[i];
}
memset(dis,0x3f,sizeof dis);
for(int i=1;i<=n;i++){
dis[i][i]=0;
}
for(int i=1,u,v;i<n;i++){
cin>>u>>v;
e[u].pb(v),e[v].pb(u);
dis[u][v]=dis[v][u]=1;
}
for(int k=1;k<=n;k++){
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]);
}
}
}
// for(int i=1;i<=n;i++){
// for(int j=1;j<=n;j++){
// cout<<dis[i][j]<<" ";
// }
// puts("");
// }
dfs1(1,0);
// for(int i=1;i<=n;i++){
// for(int j=1;j<=n;j++){
// printf("%2d ",f[i][j]);
// }
// puts("");
// }
int res=inf;
for(int i=1;i<=n;i++){
if(res>f[1][i]){
res=f[1][i],ans[1]=i;
}
}
cout<<res<<"\n";
dfs2(1,0);
for(int i=1;i<=n;i++){
cout<<ans[i]<<" ";
}
return 0;
}
}
signed main(){return asbt::main();}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步