题目链接
题目大意:
软件组件之间可能会有依赖关系,例如,TELNET和FTP都依赖于TCP/IP。你的任务是模拟安装和卸载软件组件的过程。首先是一些DEPEND指令,说明软件之间的依赖关系(保证不存在循环依赖),然后是一些INSTALL、REMOVE和LIST指令,如表6-1所示。
表6-1 指令说明
指令说明:
DEPEND item1 item2 | [item3 …] item1依赖组件item2, item3, … |
INSTALL item1 | 安装item1和它的依赖(已安装过的不用重新安装) |
REMOVE item1 | 卸载item1和它的依赖(如果某组件还被其他显式安装的组件所依赖,则不能卸载这个组件) |
LIST | 卸载item1和它的依赖(如果某组件还被其他显式安装的组件所依赖,则不能卸载这个组件) |
在INSTALL指令中提到的组件称为显式安装,这些组件必须用REMOVE指令显式删除。同样地,被这些显式安装组件所直接或间接依赖的其他组件也不能在REMOVE指令中删除。每行指令包含不超过80个字符,所有组件名称都是大小写敏感的。指令名称均为大写字母。
分析:
题意让我理解了半天,显式安装便是直接INSTALL安装上的组件,而隐式安装为因为依赖关系被安装上的组件。
这样一想,依赖关系就有点像拓扑了,可以按照拓扑的思想走。
我用了一个
map<string,pair<vector<string>,vector<string>>> map1;//first 依赖 second 被依赖
来记录依赖和被依赖关系,然后递归安装卸载即可。但一定要注意显式安装和隐式安装的情况,会决定题目的输出。
#include <bits/stdc++.h>
using namespace std;
const int maxn = 100000;
//first 依赖 second 被依赖
map<string,pair<vector<string>,vector<string>>> map1;
vector<string> installed;
map<string,int> statues;
bool is_needed(const string &str) {
auto vec = map1[str].second;
for (const auto &i : vec) {
if(statues[i]) return true;
}
return false;
}
void Install(string str, bool flag) {
if(!statues[str]) {
auto vec = map1[str].first;
for (const auto &i : vec)
Install(i,false);
if(flag) statues[str] = 1;
else statues[str] = 2;
installed.push_back(str);
cout << " Installing " << str << endl;
}
}
void Remove(string str, bool flag) {
if((flag || statues[str]==2) && !is_needed(str)){
cout << " Removing " << str << endl;
statues[str] = 0;
auto vec = map1[str].first;
auto it = find(installed.begin(), installed.end(), str);
installed.erase(it);
for(const auto &i : vec)
Remove(i,false);
}
}
int main() {
freopen("i.txt","r",stdin);
freopen("o.txt","w",stdout);
string str;
while(getline(cin,str)) {
cout << str << endl;
if(str=="END") break;
stringstream s(str);
string temp,t[maxn];
int cnt = 0;
while(s>>temp)
t[cnt++] = temp;
if(t[0]=="DEPEND") {
for(int i = 2; i < cnt; i++) {
map1[t[1]].first.push_back(t[i]);
map1[t[i]].second.push_back(t[1]);
}
}
else if(t[0]=="INSTALL") {
if(!statues[t[1]])
Install(t[1],true);
else
cout << " " << t[1] << " is already installed." << endl;
}
else if(t[0]=="REMOVE") {
if(!statues[t[1]])
cout << " " << t[1] << " is not installed." << endl;
else {
if(is_needed(t[1]))
cout << " " << t[1] << " is still is_needed." << endl;
else Remove(t[1],true);
}
}
else {
for (const auto &i : installed)
cout << " " << i << endl;
}
}
}