时间限制:3.000秒
题目链接:http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=24&page=show_problem&problem=447
刘汝佳紫书第六章最后一道例题,放到数据结构这章里面,其实就是个模拟题。
题目是给出了五种指令,DEPEND、INSTALL、REMOVE、LIST、END,操作的格式及功能如下:
DEPEND item1 item2 (item3 ...) 安装item1需要先安装item2(、item3……) INSTALL item1 安装item1,如果item1依赖其他组件,则先安装其依赖的其他组件 REMOVE item1 移除item1及其依赖的全部组件,如果组件被其他程序依赖,则不移除 LIST 输出当前已安装的所有组件 END 结束程序
INSTALL指令中作为参数的组件的安装是显式安装,其所依赖的组件的安装不是显示安装。被显式安装的组件只能通过REMOVE指令显式删除,而移除中的组件如果当前被其他显式安装的组件直接或间接地依赖,则不能通过REMOVE移除。
每当输入指令之后,先原样输出一遍指令,然后执行指令。安装组件时如果可以安装组件则需输出“Installing 组建名”。如果显式安装时组件已被安装则提示“组建名 is already installed.”,隐式安装则无需提示。如果显式删除组件时组件未被安装则提示“组建名 is not installed.”,如果组件被其他组件依赖则提示“组建名 is still needed.”,隐式卸载则无需提示。
总的来说就是那种难度不大,只是麻烦的模拟题,也不是很麻烦,至少比UVa207那样的省事儿多了……
实现起来的话就是考虑用怎样的数据结构 了。
为了实现依赖关系,我们可以建立两个类似邻接表一样的结构,一个depend一个depended,depend[x]中存组件x依赖的组件,depended[x]中存依赖组件x的组件。安装和移除组件的时候就可以直接在两个结构中查询需要安装和移除的组件了。
在这两个结构之上,我们还要注意被其他组件依赖不能移除的情况,因此建立status数组,status[x]表示x当前的状态,是未安装,还是显式安装,还是隐式安装。在卸载组件item的时候,先在depended[item]中检查是否有其他程序依赖,如果没有的话移除item,将status[item]置为0,然后递归移除depend[item]中item所依赖的组件。
为了实现LIST指令,我们再建立一个installed数组来存当前已安装的组件,每当安装新的组件时就将其放入installed数组,每当成功移除组件时就将其从数组中删除。
另外,上面我们所讲的结构和算法基于的组件都是用整数代表的,然而输入的组件名是字符串,因此还应当实现整数和字符串之间的一一对应,这里我用的办法是map,方法也很简单,在代码中已经提供。
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std; const int MAXN = 1024000; map
name2id; string id2name[MAXN]; // 名字与ID的一一对应 vector
depend[MAXN], depended[MAXN]; // 依赖与被依赖 int status[MAXN]; // 状态,0为未安装,1为显式,2为隐式 vector
installed; // 已安装的软件 int id(const string &s) { if(name2id.count(s)) return name2id[s]; else { int d = name2id.size(); name2id[s] = d; id2name[d] = s; return d; } } inline string& name(const int &id) { return id2name[id]; } bool needed(const int &item) { // 是否被其他软件依赖 for(int i = 0; i != depended[item].size(); ++i) if(status[depended[item][i]]) return true; return false; } inline void ins(const int &item, const bool &toplevel) { // 安装 if(!status[item]) { for(int i = 0; i != depend[item].size(); ++i) ins(depend[item][i], false); cout << " Installing " << name(item) << '\n'; status[item] = toplevel ? 1 : 2; installed.push_back(item); } else if(toplevel) cout << " " << name(item) << " is already installed." << '\n'; } inline void del(const int &item, const bool &toplevel) { // 移除 if(toplevel && !status[item]) cout << " " << name(item) << " is not installed." << '\n'; else if(toplevel && needed(item)) cout << " " << name(item) << " is still needed." << '\n'; else if((toplevel || status[item] == 2) && !needed(item)) { status[item] = 0; installed.erase(find(installed.begin(), installed.end(), item)); cout << " Removing " << name(item) << endl; for(int i = 0; i < depend[item].size(); i++) del(depend[item][i], false); } } inline void list() { for(int i = 0; i != installed.size(); ++i) cout << " " << name(installed[i]) << '\n'; } // 显示已安装软件 inline void setdepend(istringstream &ss) { // 建立依赖关系 string s1, s2; ss >> s1; int id1 = id(s1); while(ss >> s2) { int id2 = id(s2); depend[id1].push_back(id2); depended[id2].push_back(id1); } } int main() { ios::sync_with_stdio(false); string cmd; while(getline(cin, cmd)) { cout << cmd << endl; istringstream line(cmd); line >> cmd; if(cmd == "END") break; if(cmd[0] == 'L') list(); else if(cmd[0] == 'D') setdepend(line); else if(cmd[0] == 'I') { string s; line >> s; ins(id(s), true); } else if(cmd[0] = 'R') { string s; line >> s; del(id(s), true); } } return 0; }