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\)(话说这题部分分真的水)
posted @ 2022-08-03 20:50  Star_LIcsAy  阅读(114)  评论(0)    收藏  举报