例题6-21 UVA506 System Dependencies(67行AC代码)

紫书刷题进行中,题解系列【GitHub|CSDN

例题6-21 UVA506 System Dependencies(67行AC代码)

题目大意

把每个命令要做的事理清,代码很简单

本题的问题背景极有实际意义,例如

  • Linux下各种包管理器
  • 开发应用程序时配置管理,如springboot框架等

给定组件的依赖关系,根据命令输出相应信息,四种命令如下:

  • DEPEND item1 item2 [item3 ...] :item1 依赖于item2 (and item3 …)
  • INSTALL item1:安装 item1 和它的依赖(若有多个依赖则按照输入依赖的顺序处理)
  • REMOVE item1:移除item1,和它的依赖(当且仅当它的依赖为隐式安装此时不再被其它组件依赖;若有多个依赖则按照输入依赖的顺序处理)
  • LIST:按安装顺序输出已安装的组件

其中install item成功的项目称作显示安装

算法设计

为了提高效率,将字符串缓存与数组中,并用map存储相应编号,后续所有操作均存储id即可

map<string, int> idMp; // 名字->id
vector<string> name; // 组件名字缓存

为了便于处理依赖关系,定义before和after,其中before[i]表示i依赖的前置组件,after[i]表示依赖于i的后置组件;定义status区分安装状态;installed仅仅是为了List命令服务

map<int,vector<int> > before, after; // 依赖的项目,被项目依赖
vector<int> installed; // 已安装列表
int status[maxn]={0}; // 0:未安装;1:已显示安装;2:隐式安装

至于安装和删除都可以递归进行(输出顺序不同,对应为后序和先序),注意只有显示删除命令才可以删除显式安装

注意点

  • 样例输出中倒数第二个删除命令的Removing HTML和 Removing TCPIP顺序反了
  • 注意安装时已存在,删除时不存在的情况

AC代码(C++11,字符串处理,命令处理)

#include<bits/stdc++.h>
using namespace std;
const int maxn=10010; // 最大点数
map<string, int> idMp; // 名字->id
vector<string> name; // 组件名字缓存
map<int,vector<int> > before, after; // 依赖的项目,被项目依赖
vector<int> installed; // 已安装列表
int status[maxn]={0}; // 0:未安装;1:已显示安装;2:隐式安装
int getId(string s) { // 手动分配id
    if (idMp.find(s) == idMp.end()) { // 不存在,手动分配
        idMp[s] = name.size();
        name.push_back(s);
    }
    return idMp[s]; // 已存在,直接返回
}
void List() { // 按安装顺序打印已安装列表
    for (auto s : installed) printf("   %s\n", name[s].c_str());
}
void Install(int i, bool isTop) { // 递归安装
    if (status[i] != 0 && isTop) printf("   %s is already installed.\n", name[i].c_str()); // 已安装
    if (status[i] == 0) { // 未安装
        for (int j : before[i]) Install(j, false); // 递归安装前置依赖
        printf("   Installing %s\n", name[i].c_str());
        status[i] = (isTop ? 1 : 2); // 顶部为显示依赖,其余为隐式依赖
        installed.push_back(i); // 存于安装列表
    } 
}
bool isNeed(int i) { // 判断i是否被依赖
    for (int j : after[i]) if (status[j] != 0) return true; // 遍历后置节点
    return false;
}
void Remove(int r, bool isTop) { // 递归移除
    if (status[r] == 0 && isTop) printf("   %s is not installed.\n", name[r].c_str()); // 未安装
    if (status[r] != 0 && isTop && isNeed(r)) printf("   %s is still needed.\n", name[r].c_str()); // 存在依赖
    if (status[r] != 0 && !isNeed(r)) { // 不被需要
        printf("   Removing %s\n", name[r].c_str());
        status[r] = 0; // 状态置0,未安装
        installed.erase(find(installed.begin(), installed.end(), r)); // 删除安装列表中相应信息
        for (int j : before[r]) if (status[j] == 2) Remove(j, false); // 仅删除隐式依赖
    }
}
int main() {
    string line, cmd, sa, sb;
    while (getline(cin, line)) {
        cout <<line <<endl; // 输出原命令
        if (line[0] == 'E') { // 初始化数据结构
            idMp.clear(); name.clear(); before.clear(); after.clear(); installed.clear();
            memset(status, 0, sizeof(status));
            continue; // 进入下一组数据输入
        }
        stringstream input(line); // 流分割
        input >>cmd; // 命令
        if (cmd[0] == 'L') List(); // 显示已安装列表
        else {
            input >>sa;
            if (cmd[0] == 'D') { // 增加依赖
                while (input >>sb) {
                    before[getId(sa)].push_back(getId(sb)); // sa依赖于sb
                    after[getId(sb)].push_back(getId(sa)); // sb被sa依赖
                }
            }
            else if (cmd[0] == 'I') Install(getId(sa), true); // 安装
            else if (cmd[0] == 'R') Remove(getId(sa), true); // 删除
        }
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值