UVA ~ 506 ~ System Dependencies (DFS + 模拟)

本文介绍了一种模拟软件组件安装与卸载过程的方法,包括处理依赖关系、显式和隐式安装的区别,以及如何通过算法高效实现这些操作。

 

题意:软件组件之间可能会有依赖关系,例如,TELNEL和FTP都依赖于TCP/IP。你的任务是模拟安装和卸载软件的组件的过程,首先是一些DEOEND指令,说明软件之间的依赖关系(保证不存在循环依赖),然后是一些INSTALL,REMOVE和LIST指令,如表6-1所示。

 

 

 

 

DEPEND item1 item2 [item3 ...]

iitem1 依赖组件item2,item3,...

INSTALL item1

安装item1和他的依赖(已安装过得不用重新安装)

REMOVE item1卸载item1和他的依赖(如果某组件还被其他显式安装的组件所依赖,则不能卸载这个组件)
LIST输出所有已安装组件

 

 

 

 

 

 

在INSTALL指令中提到的组件称为显式安装,这些组件必须用REMOVE指令显式删除。同样地,被这些显式安装组件所直接或间接依赖的其他组件也不能在REMOVE指令中删除。

每行指令包含不超过80个字符,所有组件名称都是大小写敏感的。指令名称均为大写字母。

【分析】

这道题目在概念上并没有什么难点,但是有一些细节问题容易写错。首先,维护一个组件名字列表,这样可以把输入中的组件名字列表,这样可以把输入中的组件名全部转化为整数编号。接下来用两个vector数组depend[x]和depend2分别表示组件x所依赖的组件列表和依赖于x的组件列表(即当读到DEPEND x y时要把y加入depend[x],把x加入depend2[y]),这样就可以方便地安装,删除组件,以及判断某个组件是否仍然需要了。

为了区分显式和隐式安装,需要一个数组status[x],0表示组件x未安装,1表示显式安装,2表示隐式安装。

删除的顺序相反:首先判断本组件是否能删除,如果可以删除,在删除之后再递归删除它所依赖的组件。

以上内容来自《算法竞赛入门经典》

补充:输入有一堆字符串,处理到END结束,每次处理前先输出一下这句指令。用stringstream可以很方便的处理输入。

 

#include<bits/stdc++.h>
using namespace std;
const int MAXN = 10005;
int cnt = 0;
map<string, int> nameid;
string name[MAXN];
vector<int> depend[MAXN], depend2[MAXN];
int status[MAXN]; // 0-not installed, 1-explicitly installed, 2-implicitly installed
vector<int> installed;//安装列表
int ID(string s)
{
    if (!nameid.count(s)) name[cnt] = s, nameid[s] = cnt++;
    return nameid[s];
}
void INSTALL(int item, bool toplevel)
{
    if (!status[item])//没有被安装过
    {
        for (int i = 0; i < depend[item].size(); i++)
            INSTALL(depend[item][i], false);
        cout << "   Installing " << name[item] << "\n";
        status[item] = toplevel ? 1 : 2;
        installed.push_back(item);
    }
}
bool needed(int item)//该组件是否还被需要
{
    for (int i = 0; i < depend2[item].size(); i++)
        if (status[depend2[item][i]]) return true;
    return false;
}
void REMOVE(int item, bool toplevel)
{
    //不需要了且(被隐式安装或者被显式卸载)
    if ((toplevel || status[item] == 2) && !needed(item))
    {
        status[item] = 0;//表示已经卸载
        installed.erase(remove(installed.begin(), installed.end(), item),
                        installed.end());
        cout << "   Removing " << name[item] << "\n";
        for(int i = 0; i < depend[item].size(); i++)
            REMOVE(depend[item][i], false);
    }
}
void LIST()
{
    for (int i = 0; i < installed.size(); i++)
        cout << "   " << name[installed[i]] << "\n";
}
int main()
{
    //freopen("C:\\Users\\张松超\\Desktop\\in.txt", "r", stdin);
    //freopen("C:\\Users\\张松超\\Desktop\\out.txt", "w", stdin);
    memset(status, 0, sizeof(status));
    string line, cmd;
    while (getline(cin, line))
    {
        cout << line << "\n";
        stringstream ss(line);
        ss >> cmd;
        if (cmd[0] == 'E') break;
        if (cmd[0] == 'L') LIST();
        else
        {
            string item1, item2;
            int i1, i2;
            ss >> item1;
            i1 = ID(item1);
            if (cmd[0] == 'D')
            {
                while (ss >> item2)
                {
                    i2 = ID(item2);
                    depend[i1].push_back(i2);
                    depend2[i2].push_back(i1);
                }
            }
            else if (cmd[0] == 'I')
            {
                if (status[i1]) cout << "   " << item1 << " is already installed.\n";
                else INSTALL(i1, true);
            }
            else if (cmd[0] == 'R')
            {
                if(!status[i1]) cout << "   " << item1 << " is not installed.\n";
                else if(needed(i1)) cout << "   " << item1 << " is still needed.\n";
                else REMOVE(i1, true);
            }
        }
    }
    return 0;
}
/*

*/

 

 

 

 

PS C:\Users\root\StudioProjects\demo> ./gradlew clean --refresh-dependencies # Linux/Mac ./gradlew : 无法将“./gradlew”项识别为 cmdlet、函数、脚本文件或可运行程序的名称。请检查名称的拼写,如果包括路径,请确保路径正确,然后再试一次。 所在位置 行:1 字符: 1 + ./gradlew clean --refresh-dependencies # Linux/Mac + ~~~~~~~~~ + CategoryInfo : ObjectNotFound: (./gradlew:String) [], CommandNotFoundException + FullyQualifiedErrorId : CommandNotFoundException PS C:\Users\root\StudioProjects\demo> gradlew clean --refresh-dependencies # Windows gradlew : 无法将“gradlew”项识别为 cmdlet、函数、脚本文件或可运行程序的名称。请检查名称的拼写,如果包括路径,请确保路径正确,然后再试一次。 所在位置 行:1 字符: 1 + gradlew clean --refresh-dependencies # Windows + ~~~~~~~ + CategoryInfo : ObjectNotFound: (gradlew:String) [], CommandNotFoundException + FullyQualifiedErrorId : CommandNotFoundException PS C:\Users\root\StudioProjects\demo> ./gradlew projects ./gradlew : 无法将“./gradlew”项识别为 cmdlet、函数、脚本文件或可运行程序的名称。请检查名称的拼写,如果包括路径,请确保路径正确,然后再试一次。 所在位置 行:1 字符: 1 + ./gradlew projects + ~~~~~~~~~ + CategoryInfo : ObjectNotFound: (./gradlew:String) [], CommandNotFoundException + FullyQualifiedErrorId : CommandNotFoundException PS C:\Users\root\StudioProjects\demo>
最新发布
09-18
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值