Components ofcomputer systems often have dependencies--other components that must beinstalled before they will function properly. These dependencies are frequentlyshared by multiple components. For example, both the TELNET client program andthe FTP client program require that the TCP/IP networking software be installedbefore they can operate. If you install TCP/IP and the TELNET client program,and later decide to add the FTP client program, you do not need to reinstallTCP/IP.
For some components it would not be a problem if the components on which theydepended were reinstalled; it would just waste some resources. But for others,like TCP/IP, some component configuration may be destroyed if the component wasreinstalled.
It is useful to be able to remove components that are no longer needed. Whenthis is done, components that only support the removed component may also beremoved, freeing up disk space, memory, and other resources. But a supportingcomponent, not explicitly installed, may be removed only if all componentswhich depend on it are also removed. For example, removing the FTP clientprogram and TCP/IP would mean the TELNET client program, which was not removed,would no longer operate. Likewise, removing TCP/IP by itself would cause thefailure of both the TELNET and the FTP client programs. Also if we installedTCP/IP to support our own development, then installed the TELNET client (whichdepends on TCP/IP) and then still later removed the TELNET client, we would notwant TCP/IP to be removed.
We want a program to automate the process of adding and removing components. Todo this we will maintain a record of installed components and componentdependencies. A component can be installed explicitly in response to a command(unless it is already installed), or implicitly if it is needed for some othercomponent being installed. Likewise, a component, not explicitly installed, canbe explicitly removed in response to a command (if it is not needed to supportother components) or implicitly removed if it is no longer needed to supportanother component. Installing an already implicitly-installed component won'tmake that component become explicitly installed.
The input willcontain a sequence of commands (as described below), each on a separate linecontaining no more than eighty characters. Item names are case sensitive, andeach is no longer than ten characters. The command names(DEPEND, INSTALL, REMOVE and LIST) always appear inuppercase starting in column one, and item names are separated from the commandname and each other by one or more spaces. Allappropriate DEPEND commands will appear before the occurrence ofany INSTALL command that uses them. There will be no circulardependencies. The end of the input is marked by a line containing only theword END.
Command Syntax | Interpretation/Response |
DEPEND item1 item2 [item3 ...] | item1 depends on item2 (and item3 ...) |
INSTALL item1 | install item1 and those on which it depends |
REMOVE item1 | remove item1, and those on which it depends, if possible |
LIST | list the names of all currently-installed components |
Echo each line ofinput. Follow each echoed INSTALL or REMOVE line with theactions taken in response, making certain that the actions are given in theproper order. Also identify exceptional conditions (see Sample Output, below,for examples of all cases). For the LIST command, display the names of thecurrently installed components in the installation order. No output, except theecho, is produced for a DEPEND command or the linecontaining END. There will be at most one dependency list per item.
DEPEND TELNET TCPIP NETCARD
DEPEND TCPIP NETCARD
DEPEND DNS TCPIP NETCARD
DEPEND BROWSER TCPIP HTML
INSTALL NETCARD
INSTALL TELNET
INSTALL foo
REMOVE NETCARD
INSTALL BROWSER
INSTALL DNS
LIST
REMOVE TELNET
REMOVE NETCARD
REMOVE DNS
REMOVE NETCARD
INSTALL NETCARD
REMOVE TCPIP
REMOVE BROWSER
REMOVE TCPIP
END
DEPEND TELNETTCPIP NETCARD
DEPEND TCPIP NETCARD
DEPEND DNS TCPIP NETCARD
DEPEND BROWSER TCPIP HTML
INSTALL NETCARD
InstallingNETCARD
INSTALL TELNET
InstallingTCPIP
InstallingTELNET
INSTALL foo
Installingfoo
REMOVE NETCARD
NETCARD isstill needed.
INSTALL BROWSER
InstallingHTML
InstallingBROWSER
INSTALL DNS
InstallingDNS
LIST
NETCARD
TCPIP
TELNET
foo
HTML
BROWSER
DNS
REMOVE TELNET
RemovingTELNET
REMOVE NETCARD
NETCARD isstill needed.
REMOVE DNS
Removing DNS
REMOVE NETCARD
NETCARD isstill needed.
INSTALL NETCARD
NETCARD isalready installed.
REMOVE TCPIP
TCPIP isstill needed.
REMOVE BROWSER
RemovingBROWSER
Removing HTML
RemovingTCPIP
REMOVE TCPIP
TCPIP is notinstalled.
END
Sample Input 2
DEPEND A B
INSTALL A
INSTALL B
REMOVE A
END
Sample Output 2
DEPEND A B
INSTALL A
Installing B
Installing A
INSTALL B
B is already installed.
REMOVE A
Removing A
Removing B
END
代码:
// UVa506 System Dependencies
// Rujia Liu
// 注意:显式安装的必须显式删除
#include<iostream>
#include<cstring>
#include<string>
#include<sstream>
#include<vector>
#include<algorithm>
#include<map>
using namespacestd;
const int maxn =10000;
int cnt = 0;
map<string,int> name2id;
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(conststring& item) {
if(!name2id.count(item)) {
name[++cnt] = item;
name2id[item] = cnt;
}
return name2id[item];
}
bool needed(intitem) {
for(int i = 0; i < depend2[item].size();i++)
if(status[depend2[item][i]]) return true;
return false;
}
void install(intitem, 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);
}
}
void remove(intitem, 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() {
string line, cmd;
memset(status, 0, sizeof(status));
while(getline(cin, line)) {
cout << line << "\n";
stringstream ss(line);
ss >> cmd;
if(cmd[0] == 'E') break;
string item1, item2;
if(cmd[0] == 'L') list();
else {
ss >> item1;
int i1 = ID(item1);
if(cmd[0] == 'D') {
while(ss >> item2) {
int 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(!status[i1]) cout <<" " << item1 <<" is not installed.\n";
else if(needed(i1)) cout <<" " << item1 <<" is still needed.\n";
else remove(i1, true);
}
}
}
return 0;
}