2014上海全国邀请赛I题 Smart Software Installer(hdu5098)(top排序)

SmartSoftware Installer

Time Limit: 2000/1000 MS(Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 288    Accepted Submission(s): 94


Problem Description

The softwareinstallation is becoming more and more complex. An automatic tool is oftenuseful to manage this process. An IT company is developing a system managementutility to install a set of software packages automatically with thedependencies. They found that reboot is often required to take effect afterinstalling some software. A software package cannot be installed until allsoftware packages it depends on are installed and take effect. 

In the beginning, they implemented a simple installation algorithm, but thesystem would reboot many times during the installation process. This will havea great impact on the user experience. After some study, they think that thisprocess can be further optimized by means of installing as much packages aspossible before each reboot.

Now, could you please design and implement this algorithm for them to minimizethe number of restart during the entire installation process?

Input

The first line isan integer n (1 <= n <= 100), which is the number of test cases. Thesecond line is blank. The input of two test cases is separated by a blank line.

Each test case contains m (1 <= n <= 1000) continuous lines and each lineis no longer than 1024 characters. Each line starts with a package name and acomma (:). If an asterisk (*) exists between the package name and the comma,the reboot operation is required for this package. The remaining line is theother package names it depends on, separated by whitespace. Empty means thatthere is no dependency for this software. For example, “a: b” means package bis required to be installed before package a. Package names consist of letters,digits and underscores, excluding other special symbols.

Assume all packages here need to be installed and all referenced packages willbe listed in an individual line to define the reboot property. It should benoted that cyclic dependencies are not allowed in this problem.

Output

For each testcase, you should output a line starting with “Case #: " (# is the No. ofthe test case, starting from 1) and containing the reboot count for this testcase. (Refer to the sample format)

Sample Input

2

 

glibc:

gcc*: glibc

 

uefi*:

gcc*:

raid_util*: uefi

gpu_driver*: uefi

opencl_sdk: gpu_drivergcc

 

 

Sample Output

Case 1: 1

Case 2: 2

 

题目意思:有一批软件需要安装,“:”前的软件需要在“:”后的软件安装完成后才能安装(“:”后面可能有多个软件),“*”表明该软件需要重启才完成安装。

求所有软件都完成安装最少重启的次数。

解题思路:

双队列top排序,用两个队列q1,q2分别来存不需要重启的软件和需要重启的软件。首先将入度的0的点加进队列,当然不需要重启的进q1,需要重启的进q2。然后删除q1中的所有节点,让与他们相连的节点的入度减1,如果发现减完入度为0,再判断其是否需要重启,并加进q1 or q2。一旦发现q1为空,那么使答案加1(即重启一次),把q2中所有元素加入q1,q2清空。如此循环直到q1,q2均为空即可。

代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<string>
#include<vector>
#include<queue>
#include<set>
#include<map>
#include<cmath>
#define INF 0xfffffff
#define MAX 1000000
#define CLR(a,b) memset((a),(b),sizeof((a)))
using namespace std;
typedef long long ll;
int edge[2005][2005];
int vis[2005];
int degree[2005];
int tot,ans;
map<string,int> mp;
queue<int>q1,q2;
void top_sort() {
    for(int i=1; i<=tot; i++)
        if(!degree[i]) {
            if(!vis[i])
                q1.push(i);
            else q2.push(i);
        }
    while(!q1.empty()||!q2.empty()) {
        if(q1.empty()&&!q2.empty()) {
            ans++;
            while(!q2.empty()) {
                int x=q2.front();
                q2.pop();
                q1.push(x);
            }
        }
        while(!q1.empty()) {
            int x=q1.front();
            q1.pop();
            for(int i=1; i<=tot; i++)
                if(edge[i][x]) {
                    degree[i]--;
                    if(!degree[i]) {
                        if(!vis[i])
                            q1.push(i);
                        else q2.push(i);
                    }
                }
        }
    }
}
void init() {
    CLR(degree,0);
    CLR(edge,0);
    CLR(vis,0);
    tot=0;
    ans=0;
    mp.clear();
    while(!q1.empty()) q1.pop();
    while(!q2.empty()) q2.pop();
}
string p,last[1005];
int main() {
    int a,b;
    int t;
    string s;
    scanf("%d",&t);
    getchar();
    getchar();
    for(int cas=1; cas<=t; cas++) {
        init();
        while(getline(cin,s)!=NULL) {
            if(s[0] == '\0')
                break;
            int len=s.size();
            int flag=0;     ///用于标记是否需要重启
            int havelast=0;    ///用于标记是否有安装的前提
            p="";
            int lastnum=-1;   ///需要先安装的个数
            for(int i=0; i<len; i++) {
                if(s[i]==' ') {
                    last[++lastnum]="";
                    continue;
                }
                if(s[i]=='*') {
                    flag=1;
                    continue;
                }
                if(s[i]==':') {
                    havelast=1;
                    continue;
                }
                if(havelast==0) p+=s[i];
                else last[lastnum]+=s[i];
            }
            if(mp.find(p)==mp.end()) mp[p]=++tot; ///发现新的软件名 并编号 便于建图
            vis[mp[p]]=flag;
            int m=0;
            while(last[m].size()>0&&m<=lastnum) {
                if(mp.find(last[m])==mp.end()) mp[last[m]]=++tot;
                edge[mp[p]][mp[last[m]]]=1;    ///建边
                m++;
            }
        }
        for(int i=1; i<=tot; i++)
            for(int j=1; j<=tot; j++)
                if(edge[i][j]) degree[i]++;
        top_sort();
        cout<<"Case "<<cas<<": "<<ans<<endl;
    }
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值