luogu4268 Directory Traversal (dfs)
题意:给一个树状的文件结构,让你求从某个文件夹出发访问到所有文件,访问路径字符串长度之和的最小值,其中,访问父节点用..表示,两级之间用/分割
做两次dfs,第一次算DownN[x]和DownS[x],分别代表从x/访问到它子树中的文件个数和长度之和
第二次算UpN[x]和UpS[x],分别代表从x/访问到不在它子树中(也就是要先往上走)的文件个数和长度之和。
最后某个点的答案就是DownS[x]+UpS[x],取最小即可。
(由于我的zz写法,还需要再单独算一下根的答案)
1 #include<bits/stdc++.h> 2 #define ll long long 3 #define pa pair<int,int> 4 using namespace std; 5 const int maxn=100010; 6 7 ll rd(){ 8 ll x=0;char c=getchar(); 9 while(c<'0'||c>'9') c=getchar(); 10 while(c>='0'&&c<='9') x=x*10+c-'0',c=getchar(); 11 return x; 12 } 13 14 ll dws[maxn],dwn[maxn],ups[maxn],upn[maxn],ans; 15 int fa[maxn],son[maxn][2],sonh[maxn],sct; 16 int N,v[maxn];char ch[20];bool isdir[maxn]; 17 18 inline void adson(int f,int s){ 19 son[sct][0]=s;son[sct][1]=sonh[f];sonh[f]=sct++;fa[s]=f; 20 } 21 22 void dfs1(int x){ 23 for(int i=sonh[x];i!=-1;i=son[i][1]){ 24 int s=son[i][0]; 25 dfs1(s);dwn[x]+=dwn[s]; 26 dws[x]+=dwn[s]*(v[s]+isdir[s])+dws[s]; 27 } 28 } 29 30 void dfs2(int x){ 31 for(int i=sonh[x];i!=-1;i=son[i][1]){ 32 int s=son[i][0];if(!isdir[s]) continue; 33 upn[s]=upn[x]+dwn[x]-dwn[s]; 34 ups[s]=ups[x]+3*upn[s]+dws[x]-dws[s]-dwn[s]*(v[s]+isdir[s]); 35 dfs2(s); 36 //printf("%d-ans:%d upn:%d ups:%d dwn:%d dws:%d \n",s,ups[s]+dws[s],upn[s],ups[s],dwn[s],dws[s]); 37 ans=min(ans,ups[s]+dws[s]); 38 } 39 } 40 41 int main(){ 42 int i,j,k; 43 N=rd();memset(sonh,-1,sizeof(sonh)); 44 for(i=1;i<=N;i++){ 45 scanf("%s",ch); 46 v[i]=strlen(ch);j=rd(); 47 if(!j) dwn[i]=1;else isdir[i]=1; 48 for(k=1;k<=j;k++) adson(i,rd()); 49 }ans=2e13; 50 dfs1(1);dfs2(1); 51 printf("%lld\n",min(ans,dws[1])); 52 }