HDU 5098 Smart Software Installer(拓扑排序+贪心)

87 篇文章 0 订阅
28 篇文章 0 订阅

Smart Software Installer

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


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 test cases. The second 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 line is no longer than 1024 characters. Each line starts with a package name and a comma (:). If an asterisk (*) 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 be noted 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_drivergcc
 

Sample Output
  
  
Case 1: 1 Case 2: 2
 

Source
 

Recommend
hujie   |   We have carefully selected several similar problems for you:   5746  5744  5743  5742  5741

题目大意:
    有一些软件,其中一些需要重启电脑后才能生效 ,而且有一些需要在一些生效之后安装(题目保证输入不会成环),问最少重启多少次才能安装全部软件。

解题思路:
    明显是一个拓扑排序,建一张图,建立每一个前置软件指向需要它的软件的有向边,不过由于有的软件需要重启,所以我们在已经不需要前置软件的软件中先优先安装不需要重启的,直至无法继续安装再安装需要重启的软件。
    这题最恶心的是输入,将近一半的代码都来处理输入了=_=
    关于贪心的部分参考了一下大神博客: http://blog.csdn.net/burglarbyexplorers/article/details/40747787

附AC代码:
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <vector>
#include <map>
#include <string>
#include <cctype>
#include <queue>
using namespace std;

const int maxn=1000+5;
string in;
bool G[maxn][maxn],reopen[maxn];//临接矩阵表示软件先后关系,记录是否需要重启
map<string,int> to_int;//软件名到数字的映射
int p_num,degree[maxn],ans;

int get_id(string &s)//将软件名转化为数字
{
    if(to_int.find(s)!=to_int.end())
        return to_int[s];
    to_int[s]=p_num++;
    return p_num-1;
}

void toposort()
{
    queue<int> que;
    int count=0;
    memset(degree,0,sizeof degree);
    for(int i=0;i<p_num;++i)//统计每个点需要的前置软件的个数
        for(int j=0;j<p_num;++j)
            if(G[i][j])
                ++degree[j];
    while(true)
    {
        int flag=false;
        for(int i=0;i<p_num;++i)//将全部已经不需要前置软件而且不用重启的软件安装
        {
            if(degree[i]==-1||reopen[i])
                continue;
            if(degree[i]==0)
            {
                flag=true;
                ++count;
                que.push(i);
                degree[i]=-1;
            }
        }
        if(!flag)//安装所有需要重启的已经不需要前置软件的软件
        {
            ++ans;
            for(int i=0;i<p_num;++i)
            {
                if(degree[i]==0)
                {
                    degree[i]=-1;
                    ++count;
                    que.push(i);
                }
            }
        }
        if(count==p_num)//已安装全部软件
            break;
        while(!que.empty())//更新前置软件数目
        {
            int temp=que.front();
            que.pop();
            for(int i=0;i<p_num;++i)
                if(G[temp][i]&°ree[i]>0)
                    --degree[i];
        }
    }
}

int main()
{
    int T;
    scanf("%d",&T);
    getchar();//读取剩下的空格
    getline(cin,in);//读取第一组之前的空行
    for(int tt=1;tt<=T;++tt)
    {
        ans=0;
        memset(G,0,sizeof G);
        memset(reopen,0,sizeof reopen);
        to_int.clear();
        p_num=0;
        while(getline(cin,in))//最后一组数据输入完成后遇到文件末尾退出
        {
            size_t len=in.size();
            if(len==0)//空行
                break;
            int pos=0;
            string name;
            for(;in[pos]!='*'&&in[pos]!=':';++pos)
                name+=in[pos];
            int now_instell=get_id(name);
            if(in[pos]=='*')//是否需要重启
                reopen[now_instell]=true;
            while(pos<len&&!isalpha(in[pos])&&in[pos]!='_')//向后移动pos至字母或末尾
                ++pos;
            while(pos<len)
            {
                string name;
                while(pos<len&&in[pos]!=' ')
                    name+=in[pos++];
                int now_need=get_id(name);
                G[now_need][now_instell]=true;
                while(pos<len&&!isalpha(in[pos])&&in[pos]!='_')//向后移动pos至字母或末尾
                    ++pos;
            }
        }
        toposort();
        printf("Case %d: %d\n",tt,ans);
    }
    
    return 0;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值