社区讨论

关于我赛时60pts竟然是因为我不知道树形背包是n^2的这件事

P13680 [IAMOI R2] 未送出的花参与者 3已保存回复 2

讨论操作

快速查看讨论及其快照的属性,并进行相关操作。

当前回复
2 条
当前快照
1 份
快照标识符
@mhjht192
此快照首次捕获于
2025/11/04 02:47
4 个月前
此快照最后确认于
2025/11/04 02:47
4 个月前
查看原帖
如题,赛时代码:
CPP
#include<bits/stdc++.h>
using namespace std;
using ll=long long;
using pii=pair<int,int>;
const int N=405,MOD=998244353;

int n;
vector<int> G[N];
int dep[N],cnt;
int fa[N];
int val[N],siz[N],res[N];
int dp[N][N];//在i子树里面删了j个点的最小代价
int tmp[N];

void dfs(int u)
{
	dep[u]=dep[fa[u]]+1;
	for(int v:G[u])
	{
		if(v==fa[u]) continue;
		fa[v]=u,dfs(v);
	}
}

void dfs2(int u)
{
	siz[u]=1,cnt++;
	memset(dp[u],0x3f,sizeof dp[u]);
	dp[u][0]=0;
	for(int v:G[u])
	{
		if(v==fa[u]||val[v]==0) continue;
		dfs2(v);
		memcpy(tmp,dp[u],sizeof dp[u]);
		for(int k1=1;k1<=cnt;k1++)
			for(int k2=0;k2+k1<=cnt;k2++)
				tmp[k2+k1]=min(dp[u][k2]+dp[v][k1],tmp[k2+k1]);
		for(int i=0;i<=n;i++) dp[u][i]=tmp[i];
		siz[u]+=siz[v];
		val[u]+=val[v];
	}
	dp[u][siz[u]]=val[u];
}

void solve()
{
	cnt=0;
	cin>>n;
	for(int i=1;i<=n;i++)
  G[i].clear(),val[i]=fa[i]=siz[i]=dep[i]=res[i]=0;
	for(int i=1;i<n;i++)
	{
		int u,v;
		cin>>u>>v;
		G[u].push_back(v);
		G[v].push_back(u);
	}
	fa[1]=1,dfs(1);
	for(int i=1;i<=n;i++)
	{
		int now=i;
		while((dep[now]-1)*2>=dep[i]) 
			now=fa[now];
		val[now]++;
	}
	dfs2(1);
	for(int i=0;i<=cnt;i++)
		if(dp[1][i]<=n) res[n-dp[1][i]]=cnt-i;
	for(int i=n;i;i--)
	{
		if(res[i]) res[i]=n-res[i]+1;
		else res[i]=res[i+1];
	}
	for(int i=1;i<=n;i++) cout<<res[i]<<" ";
	cout<<'\n';
}

int main()
{
	ios::sync_with_stdio(0);
	cin.tie(0),cout.tie(0);
	int _;
	cin>>_;
	while(_--)solve(); 
	return 0;
}
赛后:
CPP
#include<bits/stdc++.h>
using namespace std;
using ll=long long;
using pii=pair<int,int>;
const int N=1e4+5,MOD=998244353;

int n;
vector<int> G[N];
int dep[N],cnt;
int fa[N];
int val[N],siz[N],res[N];
int dp[N][N];
int du[N];

void dfs(int u)
{
	dep[u]=dep[fa[u]]+1;
	for(int v:G[u])
	{
		if(v==fa[u]) continue;
		fa[v]=u,dfs(v);
	}
}

void dfs2(int u)
{
	siz[u]=0,cnt++,dp[u][0]=0;
	for(int v:G[u])
	{
		if(v==fa[u]||val[v]==0) continue;
		dfs2(v);
		for(int k2=siz[u];k2>=0;k2--)
			for(int k1=1;k1<=siz[v]&&k1+k2<=n;k1++)
				dp[u][k2+k1]=min(dp[u][k2]+dp[v][k1],dp[u][k2+k1]);
		siz[u]+=siz[v],val[u]+=val[v];
	}
	siz[u]++;
	dp[u][siz[u]]=val[u];
}

void solve()
{
	cnt=0;
	cin>>n;
	for(int i=1;i<=n;i++)
		for(int j=0;j<=n;j++)
			dp[i][j]=1e9;
	for(int i=1;i<=n;i++)
		G[i].clear(),val[i]=fa[i]=siz[i]=dep[i]=res[i]=du[i]=0;
	int mx=0;
	for(int i=1;i<n;i++)
	{
		int u,v;
		cin>>u>>v;
		G[u].push_back(v);
		G[v].push_back(u);
		du[u]++,du[v]++;
		mx=max(mx,max(du[u],du[v]));
	}
	fa[1]=1,dfs(1);
	for(int i=1;i<=n;i++)
	{
		int now=i;
		while((dep[now]-1)*2>=dep[i]) 
			now=fa[now];
		val[now]++;
	}
	dfs2(1);
	for(int i=0;i<siz[1];i++)
		if(dp[1][i]<=n) res[n-dp[1][i]]=cnt-i;
	for(int i=n;i;i--)
	{
		if(res[i]) res[i]=n-res[i]+1;
		else res[i]=res[i+1];
	}
	for(int i=1;i<=n;i++) cout<<res[i]<<" ";
	cout<<'\n';
}

int main()
{
	ios::sync_with_stdio(0);
	cin.tie(0),cout.tie(0);
	int _;
	cin>>_;
	while(_--)solve(); 
	return 0;
}

~这警示我们一定要记好模板~

回复

2 条回复,欢迎继续交流。

正在加载回复...