HDOJ 5098 Smart Software Installer 拓扑排序

拓扑排序:

两个队列,一个放不需要重启入度为0的,一个放需要重启入度为0的....从不需要重启的队列开始,每弹出一个数就更新下入度,遇到入读为0的就加入到相应队列里,当队列空时,记录重启次数+1,交换队列..一直到两个队列都为空

Smart Software Installer

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)

Total Submission(s): 78    Accepted Submission(s): 32

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

2014上海全国邀请赛——题目重现(感谢上海大学提供题目)

#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <string>
#include <sstream>
#include <map>
#include <queue>

using namespace std;

const int maxn=2000;

map<string,int> mSI;
int nm;
bool restart[maxn];
int degree[maxn];

int hash(string name)
{
    int ret=mSI[name];
    if(ret==0)
    {
        mSI[name]=nm++;
        ret=nm-1;
    }
    return ret;
}

struct Edge
{
    int to,next;
}edge[maxn*maxn];

int Adj[maxn],Size;

void init()
{
    memset(Adj,-1,sizeof(Adj)); Size=0;
}

void add_edge(int u,int v)
{
    edge[Size].to=v; edge[Size].next=Adj[u]; Adj[u]=Size++;
}

int TUOPU()
{
    queue<int> q[2];
    int a=0,b=1;
    int n=nm-1;
    for(int i=1;i<=n;i++)
    {
        if(degree[i]==0)
        {
            if(restart[i]==true) q[b].push(i);
            else q[a].push(i);
        }
    }
    int time=0;
    while(!q[a].empty()||!q[b].empty())
    {
        while(!q[a].empty())
        {
            int u=q[a].front(); q[a].pop();
            for(int i=Adj[u];~i;i=edge[i].next)
            {
                int v=edge[i].to;
                degree[v]--;
                if(degree[v]==0)
                {
                    if(restart[v]==true) q[b].push(v);
                    else q[a].push(v);
                }
            }
        }
        if(q[b].empty()==true) continue;
        time++;swap(a,b);
    }
    return time;
}

int main()
{
    int T_T,cas=1;
    scanf("%d",&T_T);
    getchar(); getchar();
    while(T_T--)
    {
        init();
        mSI.clear(); nm=1;
        memset(restart,false,sizeof(restart));
        memset(degree,0,sizeof(degree));

        string line,name;
        while(getline(cin,line))
        {
            if(line[0]==0) break;
            istringstream sin(line);
            sin>>name;
            bool flag=false;
            int sz=name.size();
            if(name[sz-2]=='*')
            {
                flag=true;
                name[sz-2]=0;
                name.resize(sz-2);
            }
            else
            {
                name[sz-1]=0;
                name.resize(sz-1);
            }

            int to=hash(name);
            restart[to]=flag;
            while(sin>>name)
            {
                int from=hash(name);
                add_edge(from,to);
                degree[to]++;
            }
        }
        printf("Case %d: %d\n",cas++,TUOPU());
    }
    return 0;
}
时间: 2024-11-05 07:10:18

HDOJ 5098 Smart Software Installer 拓扑排序的相关文章

hdu 5098 Smart Software Installer 拓扑排序or记忆化搜索

Smart Software Installer Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 416    Accepted Submission(s): 124 Problem Description The software installation is becoming more and more complex. An a

HDOJ 2647 Reward 【逆拓扑排序+分层】

题意:每一个人的基础工资是888. 因为一部分人要显示自己水平比較高,要求发的工资要比其它人中的一个人多.问你能不能满足他们的要求,假设能的话终于一共要发多少钱,假设不能就输出-1. 策略:拓扑排序. 这道题有些难点:一:数据大,建二维数组肯定不行,要换其它的数据结构(vector, 或者是链式前向星(本题代码用的是链式前向星)): 二:要逆拓扑排序(就是将++in[b]换成++in[a]). 三要分层次(依据上一个的钱数+1就可以). 不懂什么是链式前向星 移步:http://blog.csd

hdoj 4324 Triangle LOVE【拓扑排序判断是否存在环】

Triangle LOVE Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 3566    Accepted Submission(s): 1395 Problem Description Recently, scientists find that there is love between any of two people. For

HDU5098 Smart Software Installer (top排序)

题目意思:有一批软件需要安装,":"前的软件需要在":"后的软件安装完成后才能安装(":"后面可能有多个软件),"*"表明该软件需要重启才完成安装. 求所有软件都完成安装最少重启的次数. 解题思路: 双队列top排序,用两个队列q1,q2分别来存不需要重启的软件和需要重启的软件.首先将入度的0的点加进队列,当然不需要重启的进q1,需要重启的进q2.然后删除q1中的所有节点,让与他们相连的节点的入度减1,如果发现减完入度为0,再

HDOJ 1285 确定比赛名次(拓扑排序,四种实现方法)

确定比赛名次 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 17294    Accepted Submission(s): 6888 Problem Description 有N个比赛队(1<=N<=500),编号依次为1,2,3,....,N进行比赛,比赛结束后,裁判委员会要将所有参赛队伍从前往后依次排名,但现在裁判委员会不能直

[HDOJ5098]Smart Software Installer(字符串处理,记忆化搜索)

题目链接:https://vjudge.net/problem/HDU-5098 题意:给软件安装清单,有些软件需要一些软件安装之前安装.每个软件安装前可能需要重启也可能不需要,问最少需要重启几次. 处理完字符串以后DFS,找一条需要重启的软件安装链中最长的. gao()大法好. 1 #include <bits/stdc++.h> 2 using namespace std; 3 4 const int maxn = 2020; 5 char tmp[maxn]; 6 map<stri

HDOJ 3342 Legal or Not 【拓扑排序】

题意:判断是否成环. 策略:如题. 这道题就是简单的拓扑排序题,但是要注意一点要去重复的数据.我用了两种结构体:链式前向星和邻接矩阵. 代码1:(用链式前向星)(不用增加去重) #include<stdio.h> #include<string.h> #include<queue> #define INF 0x3f3f3f3f #define MAXN 105 struct EdgeNode{ int to; int next; }edges[MAXN]; int he

hdoj 1085 确定比赛名次 【拓扑排序】

中文题,不解释. 这是我的第一道拓扑排序题,先来讲一下什么是拓扑排序: 拓扑排序其实就是如果要进行某一项活动的时候,它的基础活动要先进行.比如说,学概率论之前必须要学会高等数学,那么高等数学就是学概率论的前提条件,这就牵涉到先后课程怎么学习,就是谁先学谁后学习, 拓扑排序就是解决这类问题的. 题目链接 http://acm.hdu.edu.cn/showproblem.php?pid=1285 代码: #include<stdio.h> #include<string.h> boo

hdoj 4857 逃生(逆向拓扑排序+优先队列)

逃生 点击打开链接 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 2161    Accepted Submission(s): 608 Problem Description 糟糕的事情发生啦,现在大家都忙着逃命.但是逃命的通道很窄,大家只能排成一行. 现在有n个人,从1标号到n.同时有一些奇怪的约束条件,每个都形如:a必须在b之前