[USACO18FEB]Directory Traversal

该博客介绍了USACO竞赛中关于Directory Traversal的问题,主要内容是寻找使得到达所有文件的字符数之和最小的当前目录。通过将问题转化为树形结构,以文件夹为节点,文件为叶节点,目标是最小化从根节点到所有叶节点的路径长度和。博主提供了思路,首先计算根节点的总路径长度和各节点下的叶子总数,然后递归地计算子节点的总路径长度,调整路径时考虑加减相应字符数。博客强调在处理过程中需要使用long long类型来避免溢出。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

https://www.luogu.org/problemnew/show/P4268

题意:选一个文件夹为当前目录,求到所有文件的需要打的字符数之和最小的那个当前目录。

思路:看成一棵树,文件夹当中间结点,文件当成叶子,求的就是:选一个中间结点,使其到所有叶子的距离和最小。

先求根节点的总路径长度,同时把各结点下叶子总个数求出来,再依次由父节点的总路径长度推出子结点的总路径长度

对于一个结点u,u下面的叶子路径长度全部减去u的长度+1(/),其他不在u下面的叶子结点全部加上3(../)。

注意要开long long。

#include<bits/stdc++.h>
using namespace std;
#define maxn 100000+100

long long n,len[maxn],file[maxn],ans;
vector<long long> son[maxn];

long long dfs(long long u,long long num)
{
	long long ans=0;
	if(son[u].size()==0)return num+len[u];
	for(long long i=0;i<son[u].size();i++)ans+=dfs(son[u][i],num+len[u]+1);
	return ans;
}
long long dfs2(long long u)
{
	if(son[u].size()==0)return 1;
	for(long long i=0;i<son[u].size();i++)file[u]+=dfs2(son[u][i]);
	return file[u];
}
void dfs3(long long u,long long fa_ans)
{
	long long _ans;	
	if(son[u].size()!=0)_ans=fa_ans-file[u]*(len[u]+1)+3*(file[1]-file[u]),ans=min(ans,_ans);
	for(long long i=0;i<son[u].size();i++)dfs3(son[u][i],_ans);
}

int main()
{
//	freopen("input.in","r",stdin);
	char str[1000];long long a,b;
	cin>>n;
	for(long long i=1;i<=n;i++)
	{
		scanf("%s%lld",str,&a);
		len[i]=strlen(str);
		while(a--)
		{
			scanf("%lld",&b);
			son[i].push_back(b);
		}
	}
	dfs2(1);
	long long root=dfs(1,-(len[1]+1));
	ans=root;	
	for(long long i=0;i<son[1].size();i++)dfs3(son[1][i],root);
	cout<<ans<<endl;
	return 0;
}

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值