UVa 506 - System Dependencies

时间限制: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; } 
              
             
            
           
          
        
      
      
     
     
    
    
   
   

  

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值