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 }

 

posted @ 2018-09-08 20:49  Ressed  阅读(285)  评论(0编辑  收藏  举报