2022/8/3 启智树考试总结
麻了。
A.climb 树
(题面待补)
Solution
- 虽然看出来了是树形 \(\mathtt{DP}\),然而冥思苦想半个小时没搞出来方程的我选择直接最短路……
AC code(最短路)
#include<bits/stdc++.h>
using namespace std;
inline int read(){
int s=0,f=1;
char ch=getchar();
while(!isdigit(ch)){
if(ch=='-') f=-1;
ch=getchar();
}
while(isdigit(ch)){
s=s*10+int(ch-'0');
ch=getchar();
}
return s*f;
}
const int N=5e5+10;
int n,k;
int head[N<<2],ver[N<<4],nxt[N<<4],edge[N<<4],tot=0;
int ban[N],fa[N],dep[N<<2];
int f[N<<2],md=0;
bool vis[N<<2];
vector<int>v[N];
void add(int x,int y,int z){
ver[++tot]=y,edge[tot]=z;
nxt[tot]=head[x],head[x]=tot;
return ;
}
void dfs(int x){
dep[x]=dep[fa[x]]+1;
md=max(md,dep[x]);
add(x,n+dep[x],0);
if(!ban[x])
add(n+dep[x],x,0);
for(int i=head[x];i;i=nxt[i])
if(ver[i]<=n && ver[i]!=fa[x])
dfs(ver[i]);
return ;
}
priority_queue<pair<int,int> >p;
void count(){
p.push(make_pair(0,1));
while(!p.empty()){
int x=p.top().second;
p.pop();
if(vis[x]) continue;
vis[x]=1;
for(int i=head[x];i;i=nxt[i]){
if(f[ver[i]]<=f[x]+edge[i]) continue;
f[ver[i]]=f[x]+edge[i];
p.push(make_pair(-f[ver[i]],ver[i]));
}
}
return ;
}
int main(){
n=read(),k=read();
int w;
for(int i=2;i<=n;++i){
fa[i]=read(),w=read();
ban[i]=read();
add(fa[i],i,w);
}
memset(f,0x3f3f3f3f,sizeof(f));
f[1]=0;
dfs(1);
for(int i=2;i<=md;++i)
add(n+i-1,n+i,k);
count();
for(int i=1;i<=n;++i)
printf("%d\n",f[i]);
return 0;
}
/*
4 3
1 7 1
1 5 0
2 1 0
*/
树形 DP 写法(标程)
#include<bits/stdc++.h>
using namespace std;
const int maxn=2E6+5 ;
const int inf=INT_MAX ;
int n,k;
int size,head[maxn],dep[maxn],good[maxn];
int dis[maxn];
bool ban[maxn];
vector<int>what[maxn];
template<class T>inline void read(T &x){
char ch=getchar();
while(!isdigit(ch))
ch=getchar();
x=ch-'0';
ch=getchar();
while(isdigit(ch)){
x=x*10+ch-'0';
ch=getchar();
}
return ;
}
int G[55];
template<class T>inline void write(T x){
int g=0;
do{
G[++g]=x%10;
x/=10;
}
while(x);
for(int i=g;i>=1;--i)
putchar('0'+G[i]);
putchar('\n');
return ;
}
struct edge{
int to,next,w;
}E[maxn];
inline void add(int u,int v,int w){
E[++size].to=v;
E[size].next=head[u] ;
E[size].w=w;
head[u]=size;
return ;
}
bool vis[maxn];
inline int get(int x,int y){
assert(x<=y);
return good[x]+k*(y-x);
}
int main(){
ios::sync_with_stdio(false);
read(n),read(k);
what[0].push_back(1);
for(int i=2;i<=n;++i){
int x,y;
read(x),read(y),read(ban[i]);
dep[i]=dep[x]+1;
what[dep[i]].push_back(i);
if(ban[i])
add(x,i,y);
else add(x,i,min(y,k));
}
for(int d=1;d<n;++d)
good[d]=inf;
int pos=0;
for(int d=0;d<=n;++d){
for(int e=0;e<what[d].size();++e){
int u=what[d][e];
good[dep[u]]=min(good[dep[u]],dis[u]);
}
int g=good[d];
for(int e=0;e<what[d].size();++e){
int u=what[d][e];
if(!ban[u])
dis[u]=min(dis[u],g);
}
if(d && get(pos,d)>get(d,d))
pos=d;
for(int e=0;e<what[d].size();++e){
int u=what[d][e];
for(int i=head[u];i;i=E[i].next){
int v=E[i].to;
dis[v]=dis[u]+E[i].w;
if(!ban[v])
dis[v]=min(dis[v],get(pos,d+1));
}
}
}
for(int i=1;i<=n;++i)
write(dis[i]);
return 0;
}
B.h
(题面待补)
Solution
- 显然考场上我选择不用脑子的前 \(60pts\)
(话说这题部分分真的水);