2017-2018 ACM-ICPC, Central Europe Regional Contest (CERC 17):H. Hidden Hierarchy

题目链接: https://codeforces.com/gym/101620

题意:有一个文件夹系统,现在给你n个文件的绝对路径,你需要按字典序输出所有占用内存大于k的文件夹,如果文件夹下面还有文件夹,但是没有展示则在前方加上符号‘+’,如果该文件夹下面只有文件则前方用空格占位,否则前方输出符号‘-’。其实不懂的可以直接参照windows的系统文件显示。

解题心得:

  • 首先要知道其实文件的储存就是一棵树,所以这个题最后肯定是要建一棵树来解决的。
  • 其次是不能简单的直接把每个文件夹名字映射成数字,因为可能有相同的文件夹的名字,只要不是在同一个文件夹下有相同的名字就都可以满足。对于这个可以用这个文件的绝对路径当成这个文件的名字,然后按字典序映射成数字,建树遍历。


代码有点丑,辣眼睛

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll maxn = 1005;
const double INF = 1e9;

struct Node {
    ll va, to, va2;
}node[maxn*10000];

vector <string> ve;
vector <string> s;
vector <ll> edge[maxn*10000];

ll n, num[maxn], root, k;
map <string, ll> maps, mapsVa;
ll vis[maxn*10000];//vis[i]==1代表这个节点是文件,vis[i]==2代表这个节点下面全是文件,否则是继续混合展开

void init() {
    scanf("%lld", &n);
    for(ll i=1;i<=n;i++) {
        string st;
        cin>>st;
        s.push_back(st);
        scanf("%lld", &num[i]);
        mapsVa[st] = num[i];
    }
    scanf("%lld", &k);
}

void mapNum() {
    for(ll i=0;i<s.size();i++) {
        string st = s[i], temp;
        temp.clear();
        for(ll j=0;j<st.length();j++) {
            temp += st[j];
            if(j == st.length()-1) {
                ve.push_back(temp);
                break;
            }
            if(st[j] == '/') {
                ve.push_back(temp);
            }
        }
    }
    sort(ve.begin(), ve.end());
    ve.erase(unique(ve.begin(), ve.end()), ve.end());
    for(ll i=0;i<ve.size();i++) {
        maps[ve[i]] = i;
    }
    root = maps["/"];
}

void build_tree() {
    for(ll i=0;i<s.size();i++) {
        string st = s[i], temp;
        temp.clear();
        ll pre = -1, now = -1;
        for(ll j=0;j<st.length();j++) {
            temp += st[j];
            if(j == st.length()-1) {
                if(now != -1)
                    pre = now;
                now = maps[temp];
                edge[pre].push_back(now);
                edge[now].push_back(pre);
                node[now].va = mapsVa[temp];
                vis[now] = 1;
                break;
            }
            if(st[j] == '/') {
                ve.push_back(temp);
                if(pre == -1) {
                    pre = maps[temp];
                } else {
                    if(now != -1)
                        pre = now;
                    now = maps[temp];
                    edge[pre].push_back(now);
                    edge[now].push_back(pre);
                }
                continue;
            }
        }
    }
    for(ll i=0;i<maxn*10000;i++) {
        if(edge[i].empty()) break;
        sort(edge[i].begin(), edge[i].end());
        edge[i].erase(unique(edge[i].begin(), edge[i].end()), edge[i].end());
    }
}

ll dfs(ll pre,ll now) {
    if(edge[now].size() == 1 && now != root) {
        return node[now].va;
    }

    bool flag = true, all_small = true;
    for(ll i=0;i<edge[now].size();i++) {
        ll to = edge[now][i];
        if(to == pre) continue;
        node[now].va += dfs(now, to);
    }
    for(ll i=0;i<edge[now].size();i++) {
        ll to = edge[now][i];
        if(to == pre) continue;
        if(vis[to] != 1) flag = false;
        if(vis[to] != 1 && node[to].va >= k) all_small = false;
    }
    if(flag) vis[now] = 2;
    else if(all_small) vis[now] = 3;

    return node[now].va;
}

void Print(ll pre, ll now) {
    if(vis[now] == 1) return ;
    if(vis[now] == 2) {
        printf("  ");
        cout<<ve[now]<<" ";
        printf("%lld\n", node[now].va);
        return ;
    } else if(vis[now] == 3){
        printf("+ ");
        cout<<ve[now]<<" ";
        printf("%lld\n", node[now].va);
        return ;
    } else {
        printf("- ");
        cout<<ve[now]<<" ";
        printf("%lld\n", node[now].va);
    }

    for(ll i=0;i<edge[now].size();i++) {
        ll v = edge[now][i];
        if(v == pre) continue;
        Print(now, v);
    }
}

int main() {
    //    freopen("1.in.txt", "r", stdin);
    init();
    mapNum();
    build_tree();
    dfs(-1, root);

    Print(-1, root);
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值