Codeforces 909E(Coprocessor,双队列维护)

题意:给出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

Codeforces 909E(Coprocessor,双队列维护)
#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

 

上一篇:5.16


下一篇:【学习笔记 2】单调队列 & 单调栈