【算法竞赛入门经典】6.5[图的概念和拓扑序] 例题6-21 UVa506

【算法竞赛入门经典】6.5[图的概念和拓扑序] 例题6-21 UVa506

例题UVa506

Components of computer systems often have dependencies—other components that must be installed before they will function properly. These dependencies are frequently shared by multiple components. For example, both the TELNET client program and the FTP client program require that the TCP/IP networking software be installed before 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 reinstall TCP/IP.
For some components it would not be a problem if the components on which they depended were reinstalled; it would just waste some resources. But for others, like TCP/IP, some component configuration may be destroyed if the component was reinstalled.
It is useful to be able to remove components that are no longer needed. When this is done, components that only support the removed component may also be removed, freeing up disk space, memory, and other resources. But a supporting component, not explicitly installed, may be removed only if all components which depend on it are also removed. For example, removing the FTP client program 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 the failure of both the TELNET and the FTP client programs. Also if we installed TCP/IP to support our own development, then installed the TELNET client (which depends on TCP/IP) and then still later removed the TELNET client, we would not want TCP/IP to be removed.
We want a program to automate the process of adding and removing components. To do this we will maintain a record of installed components and component dependencies. A component can be installed explicitly in response to a command (unless it is already installed), or implicitly if it is needed for some other component being installed. Likewise, a component, not explicitly installed, can be explicitly removed in response to a command (if it is not needed to support other components) or implicitly removed if it is no longer needed to support another component. Installing an already implicitly-installed component won’t make that component become explicity installed.

Input

The input file contains several test cases, each of them as described below. The input will contain a sequence of commands (as described below), each on a separate line containing no more than eighty characters. Item names are case sensitive, and each is no longer than ten characters. The command names (DEPEND, INSTALL, REMOVE and LIST) always appear in uppercase starting in column one, and item names are separated from the command name and each other by one or more spaces. All appropriate DEPEND commands will appear before the occurrence of any INSTALL command that uses them. There will be no circular dependencies. The end of the input is marked by a line containing only the word END.
这里写图片描述

Output

For each test case, the output must follow the description below. Echo each line of input. Follow each echoed INSTALL or REMOVE line with the actions taken in response, making certain that the actions are given in the proper order. Also identify exceptional conditions (see Sample Output, below, for examples of all cases). For the LIST command, display the names of the currently installed components in the installation order. No output, except the echo, is produced for a DEPEND command or the line containing END. There will be at most one dependency list per item

Sample Input

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

Sample Output

DEPEND TELNET TCPIP NETCARD
DEPEND TCPIP NETCARD
DEPEND DNS TCPIP NETCARD
DEPEND BROWSER TCPIP HTML
INSTALL NETCARD
Installing NETCARD
INSTALL TELNET
Installing TCPIP
Installing TELNET
INSTALL foo
Installing foo
REMOVE NETCARD
NETCARD is still needed.
INSTALL BROWSER
Installing HTML
Installing BROWSER
INSTALL DNS
Installing DNS
LIST
NETCARD
TCPIP
TELNET
foo
HTML
BROWSER
DNS
REMOVE TELNET
Removing TELNET
REMOVE NETCARD
NETCARD is still needed.
REMOVE DNS
Removing DNS
REMOVE NETCARD
NETCARD is still needed.
INSTALL NETCARD
NETCARD is already installed.
REMOVE TCPIP
TCPIP is still needed.
REMOVE BROWSER
Removing BROWSER
Removing HTML
Removing TCPIP
REMOVE TCPIP
TCPIP is not installed.
END

拓扑

对一个有向无环图(Directed Acyclic Graph简称DAG)G进行拓扑排序,是将G中所有顶点排成一个线性序列,使得图中任意一对顶点u和v,若边(u,v)∈E(G),则u在线性序列中出现在v之前。通常,这样的线性序列称为满足拓扑次序(Topological Order)的序列,简称拓扑序列。

本题储存结构

为编号便于使用,采用了STL MAP的结构

map<string, int>info1;

每一个系统看成一个节点,系统之间是单向的图,由于不涉及到边上的信息,只需要储存其指向哪个节点和被哪个节点指向即可。已安装的节点也用一个vector储存。

vector<int>d[MAX];
vector<int>bd[MAX];
vector<int>installinfo;

这题的拓扑直接使用数组记录入度和出度即可。
TIP:安装方式需要保留,删除组件时有用

思路

直接利用两个vector数组记录每个节点的入度和出度。安装和删除进行dfs。

样例实现代码

TIP:本代码没有在UVa测试,仅保证样例通过。

#include<iostream>
#include<map>
#include<string>
#include<sstream>
#include<vector>
#include<algorithm>
#define MAX 1000
using namespace std;
vector<int>d[MAX];
vector<int>bd[MAX];
vector<int>installinfo;
int installed[MAX];
map<string, int>info1;
string info2[MAX];
int cnt = 0;
int ID(const string &s) {
    if (!info1.count(s)) {
        info2[cnt] = s;
        info1[s] = cnt++;
    }
    return info1[s];
}
void list() {
    for (int i = 0; i < installinfo.size(); i++)
        cout << "   " << info2[installinfo[i]] << "\n";
}
void install(int s,int level) {
    if (!installed[s]) {
        installed[s] = level;
        for (int i = 0; i < d[s].size(); i++)
            install(d[s][i], 2);
        cout << "   Installing " << info2[s] << endl;
        installed[s] = level;
        installinfo.push_back(s);
    }
}
bool need(int s) {
    for (int i = 0; i < bd[s].size(); i++)
        if (installed[bd[s][i]])
            return true;
    return false;
}
void remove(int s,int level) {
    if ((installed[s]==2||level==1)&&installed[s]&&!need(s)) {
        installed[s] = 0;
        cout << "   Removing " << info2[s] << endl;
        installinfo.erase(remove(installinfo.begin(), installinfo.end(), s), installinfo.end());
        for (int i = 0; i < d[s].size(); i++)
            remove(d[s][i], 2);
    }
}
int main() {
    memset(installed, 0, sizeof(installed));
    string raw, cmd;
    string s1, s2;
    int st1, st2;
    while (getline(cin, raw)) {
        stringstream ss(raw);
        ss >> cmd;
        if (cmd == "END")
            break;
        else if (cmd == "LIST")
            list();
        else if (cmd == "DEPEND") {
            ss >> s1;
            st1=ID(s1);
            while (ss >> s2) {
                st2 = ID(s2);
                d[st1].push_back(st2);
                bd[st2].push_back(st1);
            }
        }
        else if (cmd == "INSTALL") {
            ss >> s1;
            st1 = ID(s1);
            if (installed[st1])
                cout << "   " << s1 << " is already installed." << endl;
            else
                install(st1,1);
        }
        else if (cmd == "REMOVE") {
            ss >> s1;
            st1 = ID(s1);
            if (!installed[st1])
                cout << "   " << s1 << " is not installed." << endl;
            else if (need(st1))
                cout << "   " << s1 << " is still needed." << endl;
            else
                remove(st1,1);
        }
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值