题意:给出n个待处理的事件(0 ~n-1),再给出了n个标(0表示只能在主处理器中处理这个事件,1表示只能在副处理器中处理这个事件),处理器每次能处理多个任务。每个事件有关联,如果一个任务要在副处理器上执行,那它所依赖的任务要么已执行完了,要么和它一起在这个副处理器上同时执行。问副处理器最少调用多少次。
解法:这个题我觉得挺不错的,自己写完后看了一下别人写的题解,觉得在简易程度上没有我的好,所以自己重新写一个自己的理解。毋庸置疑是需要运用拓扑排序的,统计入度InDeg。我开2个队列,队列q1表示处理在coprocessor上的情况,队列q2处理在processor上的情况,这个题就是两个队列来回跳转(why?因为如果单队列,如果你不打ACM做工程的话单队列找点就好了,可这是ACM,会因为暴力找点而TLE)。每一次拓扑排序中如果该点没有入度了,看自己的所处的情况,如果是coprocessor的滚去q1,反之滚去q2,因为如果在同一个拓扑排序中,前面和后面都是一样的(比如都是coprocessor),这个处理完紧接着会处理下一个的,所以可以大可放心。这个题和我之前写的一个很类似,很大程度我是受了那道题的启发写的https://www.cnblogs.com/Anonytt/p/12859856.html
#include<bits/stdc++.h> #define ll long long #define rep(i,a,n) for(int i=a;i<=n;i++) #define per(i,n,a) for(int i=n;i>=a;i--) #define endl '\n' #define mem(a,b) memset(a,b,sizeof(a)) #define IO ios::sync_with_stdio(false);cin.tie(0); using namespace std; const int INF=0x3f3f3f3f; const ll inf=0x3f3f3f3f3f3f3f3f; const int mod=1e9+7; const int maxn=1e5+5; int tot,head[maxn]; struct E{ int to,next; }edge[maxn<<1]; void add(int u,int v){ edge[tot].to=v; edge[tot].next=head[u]; head[u]=tot++; } int n,m,p[maxn],indeg[maxn],vis[maxn],ans,num=0; vector<int> vec; queue<int>q1,q2; void topsort1(){ while(!q1.empty()){ int now=q1.front();q1.pop(); if(p[now]!=1) continue; if(p[now]==1) num+=1; for(int i=head[now];i!=-1;i=edge[i].next){ int v=edge[i].to; --indeg[v]; if(indeg[v]==0&&p[v]==1) q1.push(v); if(indeg[v]==0&&p[v]==0) q2.push(v); } } } void topsort2(){ while(!q2.empty()){ int now=q2.front();q2.pop(); if(p[now]!=0) continue; if(p[now]==0) num+=1; for(int i=head[now];i!=-1;i=edge[i].next){ int v=edge[i].to; --indeg[v]; if(indeg[v]==0&&p[v]==1) q1.push(v); if(indeg[v]==0&&p[v]==0) q2.push(v); } } } int main(){ cin>>n>>m;mem(head,-1); rep(i,1,n) cin>>p[i],vec.push_back(i); while(m--){ int v,u;cin>>v>>u;++u,++v; add(u,v);indeg[v]++; } int e=1; rep(i,1,n){ if(!indeg[i]&&!vis[i]&&p[i]==1) vis[i]=1,q1.push(i); if(!indeg[i]&&!vis[i]&&p[i]==0) vis[i]=1,q2.push(i); } while(num!=n){ e=1-e; if(e==1) topsort1(),ans+=1; if(e==0) topsort2(); } cout<<ans<<endl; }View Code