HDU 5098 Smart Software Installer(拓扑排序)

题目:Smart Software Installer

题意:要安装一些软件,有些软件安装完就能生效,有些需要重启。有些软件甚至要需要其它一些软件生效的情况下才能安装。

要求安装完所有软件并且全部生效的最少重启次数。

对于需要重启的软件,在它的名字后面跟着个*,冒号后面表示它所依赖的软件名称。

我们可以根据依赖关系构建有向图,比如A依赖B的话,就构造B->A,题目保证不存在环。

那么我们就可以保存好入度,用一个队列表示当前可以安装的软件;

一开始将入度为0的放进队列,逐个拿出来安装,如果需要重启,先保存起来,不需要重启的就将它指向的点全部入度减1,遇到入度变成0的就加入队列。

当队列为空时,就把那些需要重启的全部重启一下,其实就是扩展一遍,这样队列可能就会有新的软件可以安装。

这样直到全部安装完生效就可以了。

#include<cstdio>
#include<cstring>
#include<string>
#include<map>
#include<queue>
#include<vector>
#include<stack>
using namespace std;
map<string,int> MP;
stack<int> ST;
const int N = 1100;
char ss[N], s[N];
int T, t, m, in[N];
bool mk[N];
vector<int> V[N];
int getid(){
    if(!MP.count(s)){
        MP[s] = ++m;
        V[m].clear();
    }
    return MP[s];
}
void solve(){
    int ans = 0, cnt = m;
    queue<int> Q;
    for(int i=1; i<=m; i++){
        if(!in[i])  Q.push(i);
    }
    while(cnt){
        while(!Q.empty()){
            int x=Q.front(); Q.pop();
            if(mk[x])   ST.push(x);
            else{
                cnt--;
                for(int i=0; i<V[x].size(); i++){
                    int j = V[x][i];
                    if(!(--in[j]))  Q.push(j);
                }
            }
        }
        if(!cnt)    break;
        ans++;
        while(!ST.empty()){
            int x = ST.top(); ST.pop();
            cnt--;
            for(int i=0; i<V[x].size(); i++){
                int j = V[x][i];
                if(!(--in[j]))  Q.push(j);
            }
        }
    }
    printf("Case %d: %d\n", ++t, ans);
}
void init(){
    MP.clear();
    m = 0;
    memset(mk, 0, sizeof(mk));
    memset(in, 0, sizeof(in));
}
void insert(){
    int len = strlen(ss);
    bool flag = 0;
    int i, j;
    for(i=0; i<len; i++){
        if(ss[i]=='*'){
            flag = 1;
            s[i] = '\0';
            break;
        }
        if(ss[i]==':'){
            s[i] = '\0';
            break;
        }
        s[i] = ss[i];
    }
    int x = getid();
    mk[x] |= flag;
    for(i+=2, j=0; i<len; i++){
        if(ss[i]==' '){
            s[j] = '\0';
            int y = getid();
            V[y].push_back(x);
            in[x]++;
            j = 0;
        }
        else{
            s[j++] = ss[i];
        }
    }
    s[j] = '\0';
    int y = getid();
    V[y].push_back(x);
    in[x]++;
}
int main(){
    scanf("%d", &T);
    getchar();
    gets(ss);
    t = 0;
    init();
    while(gets(ss)){
        if(strcmp(ss, "")==0){
            solve();
            init();
        }
        else{
            insert();
        }
    }
    solve();
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值