HDOJ 5098 Smart Software Installer【拓扑排序】


Smart Software Installer

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

Problem Description

The software installation is becoming more and more complex. An automatic tool is often useful to manage this process. An IT company is developing a system management utility to install a set of software packages automatically with the dependencies. They found that reboot is often required to take effect after installing some software. A software package cannot be installed until all software packages it depends on are installed and take effect.

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

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

 

 

Input

The first line is an integer n (1 <= n <= 100), which is the number of testcases. The second line is blank. The input of two test cases is separated by ablank 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 a comma (:). If an a sterisk (*) exists between the package name and the comma,the reboot operation is required for this package. The remaining line is the other package names it depends on, separated by whitespace. Empty means that there is no dependency for this software. For example, “a: b” means package b is 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 will be 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 test case, you should output a line starting with “Case #: " (# is the No. of the test case, starting from 1) and containing the reboot count for this test case. (Refer to the sample format)

 

 

Sample Input

2

 

glibc:

gcc*: glibc

 

uefi*:

gcc*:

raid_util*: uefi

gpu_driver*: uefi

opencl_sdk:gpu_driver gcc

 

 

Sample Output

Case 1: 1

Case 2: 2



【题意】给出一堆需要安装的软件,软件名称以字符串的形式给出,字符串结尾带星号的是安装完需要重启才能生效,不带星号的安装完直接能生效,有的软件的名称后还有一些字符串,代表装这个软件前这些软件必须已经生效。问所有软件安装完毕并生效所需要最少重启电脑的次数。


【思路】为使重启次数最少,我们应该遵循以下步骤

(1) 先安装可以安装且不需重启的软件

(2) 然后再安装可以安装但需要重启的软件,安装完这些后重启一次.


如果还有软件没有安装的话重复(1),(2)步骤。


这个过程利用拓扑排序的知识实现。


【PS】该题输入格式有点坑爹,需要注意。然后题目样例有错误,最后一行少了一个空格,上面的题面中已经改正。



#include <cstdio>
#include <map>
#include <vector>
#include <queue>
#include <cstring>
#include <string>
#include <algorithm>
using namespace std;
#define mst(a,b) memset((a),(b),sizeof(a))
#define rush() int T;scanf("%d",&T);while(T--)

typedef long long ll;
const int maxn = 1030;
const int mod = 20090717;
const int INF = 0x3f3f3f;
const double eps = 1e-9;

int cnt;
int vis[maxn];
int degree[maxn];
char s[maxn];
char temp[maxn];
vector<int>vec[maxn];
map<string,int>mp;

int solve()
{
    int ans=0;
    queue<int>q;
    queue<int>s;
    for(int i=1;i<cnt;i++)
    {
        if(degree[i]==0)    //前置条件全部满足
        {
            if(vis[i]==0)   //不需重启
            {
                s.push(i);
            }
            else q.push(i); //需要重启
        }
    }
    while(s.size()||q.size())
    {
        if(s.size()>0)
        {
            int u=s.front();
            s.pop();
            for(int i=0;i<vec[u].size();i++)
            {
                int v=vec[u][i];
                degree[v]--;
                if(degree[v]==0)
                {
                    if(vis[v]==0) s.push(v);
                    else q.push(v);
                }
            }
        }
        else
        {
            ans++;
            while(q.size())
            {
                int u=q.front();
                q.pop();
                s.push(u);    //相当于安装后不重启直接能生效
            }
        }
    }
    return ans;
}

int main()
{
    int cas=1;
    int t;
    int u,v;
    scanf("%d",&t);
    getchar();
    getchar();
    while(t--)
    {
        cnt=1;
        mst(vis,0);
        mst(degree,0);
        mp.clear();
        while(gets(s))
        {
            if(strcmp(s,"")==0)   break;
            int pos=0;
            int len=strlen(s);
            for(int i=0; i<len; i++)
            {
                if(s[i]==':'||s[i]=='*')
                {
                    temp[pos]='\0';
                    if(mp[temp]==0) mp[temp]=cnt++;
                    u=mp[temp];
                    if(s[i]==':') i++;
                    else
                    {
                        i+=2;
                        vis[u]=1;
                    }
                    pos=0;
                }
                else if(s[i]==' ')
                {
                    temp[pos]='\0';
                    if(mp[temp]==0) mp[temp]=cnt++;
                    v=mp[temp];
                    degree[u]++;
                    vec[v].push_back(u);
                    pos=0;
                }
                else
                {
                    temp[pos++]=s[i];
                    if(i==len-1)
                    {
                        temp[pos]='\0';
                        if(mp[temp]==0) mp[temp]=cnt++;
                        v=mp[temp];
                        degree[u]++;
                        vec[v].push_back(u);
                        pos=0;
                    }
                }
            }
        }
        int ans=solve();
        printf("Case %d: %d\n",cas++,ans);
        for(int i=1;i<=cnt;i++)
        {
            vec[i].clear();
        }
    }
    return 0;
}



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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值