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()); } }