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] == '\0')
                break;
            istringstream sin(s);
            sin >> name;
            int len = strlen(name),flag = 0;
            if(name[len - 2] == '*'){
                flag = 1;
                name[len - 2] = '\0';
            }else
                name[len - 1] = '\0';
            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\n",cas++,topo());
    }
}


發佈了165 篇原創文章 · 獲贊 1 · 訪問量 9萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章