zoukankan      html  css  js  c++  java
  • hdu 5098 双队列拓扑排序

    http://acm.hdu.edu.cn/showproblem.php?pid=5098

    软件在安装之后需要重启才能发挥作用,现在给你一堆软件(有的需要重启有的不需要)以及安装这个软件之前需要哪些软件发挥作用,求最少的重启次数


    可以看出是拓扑排序,但是需要用两个队列q1,q2分别来存 不需要重启的software 和 需要重启的software。根据题目输入建好图后,按照拓扑序规则,首先将入度的0的点加进队列,不需要重启的进q1,需要的进q2。然后处理q1中的所有节点(即要删除这些点),那么要让与他们相连的节点的入度减1,如果发现减完入度为0,再判断其是否需要重启,并加进q1 or q2。一旦发现q1为空,那么使答案加1(不能继续任何安装即重启一次),把q2中所有元素加入q1,q2清空。如此循环直到q1,q2均为空即可。

    #include <cstdio>
    #include <cstdlib>
    #include <cmath>
    #include <cstring>
    #include <string>
    #include <queue>
    #include <map>
    #include <iostream>
    #include <sstream>
    #include <algorithm>
    using namespace std;
    #define RD(x) scanf("%d",&x)
    #define RD2(x,y) scanf("%d%d",&x,&y)
    #define RD3(x,y,z) scanf("%d%d%d",&x,&y,&z)
    #define clr0(x) memset(x,0,sizeof(x))
    #define clr1(x) memset(x,-1,sizeof(x))
    #define eps 1e-9
    const double pi = acos(-1.0);
    typedef long long LL;
    const int maxn = 1050;
    map <string , int> mp;
    int ecnt,cnt;
    int reboot[maxn],out[maxn],in[maxn];
    struct edge{
        int v,next;
    }e[maxn*maxn];
    int head[maxn],vis[maxn];
    void init()
    {
        mp.clear();
        ecnt = cnt = 0;
        clr0(in),clr0(out),clr0(reboot);
        clr1(head),clr0(vis);
    }
    void add(int u,int v)
    {
        e[ecnt].next = head[u];
        e[ecnt].v = v;
        head[u] = ecnt++;
    }
    int topo(){
        queue<int> q1,q2;// 不需要重启的进q1,需要的进q2
        for(int i = 1;i <= cnt;++i)if(in[i] == 0){
            if(reboot[i] == 0)
                q1.push(i);
            else
                q2.push(i);
        }
        int ans = 0;
        while(!q1.empty() || !q2.empty()){
            if(q1.empty() && !q2.empty()){
                ans++;
                while(!q2.empty()){
                    q1.push(q2.front());
                    q2.pop();
                }
            }
            while(!q1.empty()){
                int u = q1.front();q1.pop();
                vis[u] = 1;
                for(int i = head[u];i != -1;i = e[i].next){
                    int v = e[i].v;
                    in[v]--;
                    if(in[v] == 0){
                        if(reboot[v] == 0)
                            q1.push(v);
                        else
                            q2.push(v);
                    }
                }
            }
        }
        return ans;
    }
    int main()
    {
        string s;
        char name[1050];
        int _,cas = 1;RD(_);getchar();getchar();
        while(_--)
        {
            init();
            while(getline(cin,s)){
                if(s[0] == '')
                    break;
                istringstream sin(s);
                sin >> name;
                int len = strlen(name),flag = 0;
                if(name[len - 2] == '*'){
                    flag = 1;
                    name[len - 2] = '';
                }else
                    name[len - 1] = '';
                string id = name,_id;
                if(mp.find(id) == mp.end())
                    mp[id] = ++cnt;
                reboot[mp[id]] = flag;
                while(sin >> _id){
                    if(mp.find(_id) == mp.end())
                        mp[_id] = ++cnt;
                    add(mp[_id],mp[id]);
                    out[mp[_id]]++;
                    in[mp[id]]++;
                }
            }
            printf("Case %d: %d
    ",cas++,topo());
        }
    }
    


  • 相关阅读:
    pom.xml配置
    Eclipse将引用了第三方jar包的Java项目打包成jar文件的两种方法
    jar文件运行打断点
    prim算法
    Kruscal algorithm
    递归程序设计思想(看图思考2小时)
    广义表的实现(法二)
    广义表的实现
    有错误的地宫寻宝问题
    写一个数的所有加法算式
  • 原文地址:https://www.cnblogs.com/zibaohun/p/4074364.html
Copyright © 2011-2022 走看看