题意:有两个实验室,有n个实验和m对实验依赖(a,b)代表实验b必须在实验a之后才能进行,一开始可以在任意两个实验室进行实验,问最少要转移多少次实验室可以把这n个实验全部完成。
两次拓扑排序分别计算从1号实验室开始和从2号实验室开始所需要转移的次数就可以。。。
代码:
#include <iostream> #include <cstdio> #include <cstring> #include <queue> using namespace std; const int MAXN = 100000+1; int n,m,T; struct Edge { int to,next; Edge(){} Edge(int _to,int _next):to(_to),next(_next){} }e[1000000+5]; int head[100000+1],tot; void init(){ for(int i=1;i<=n;i++)head[i]=-1;
tot=0; } void AddEdge(int u,int v){ e[tot]=Edge(v,head[u]); head[u]=tot++; } void Read(int &x){ char ch; while((ch=getchar())&&!isdigit(ch)); x=0; do { x=(x<<1)+(x<<3)+(ch^48); }while((ch=getchar())&&isdigit(ch)); } int que1[MAXN*2],que2[MAXN*2]; int front1,rear1,front2,rear2; int du[MAXN],type[MAXN],du1[MAXN];
int countt(){ front1=rear1=front2=rear2=0; for(int i=1;i<=n;i++){ du1[i]=du[i]; if(du[i]==0){ if(type[i]==1) que1[rear1++]=i; if(type[i]==2) que2[rear2++]=i; --du[i]; } } int cnt=0; int pre=1; while((front1!=rear1)||(front2!=rear2)){ int tf=0; while(front1!=rear1){ tf=1; int u=que1[front1++]; for(int i=head[u];i!=-1;i=e[i].next){ int v=e[i].to; du[v]--; if(du[v]==0){ if(type[v]==1)que1[rear1++]=v; if(type[v]==2)que2[rear2++]=v; du[v]--; } } } if(tf&&pre!=1){ pre=1;++cnt; } tf=0; while(front2!=rear2){ tf=1; int u=que2[front2++]; for(int i=head[u];i!=-1;i=e[i].next){ int v=e[i].to; du[v]--; if(du[v]==0){ if(type[v]==1)que1[rear1++]=v; if(type[v]==2)que2[rear2++]=v; du[v]--; } } } if(tf&&pre!=2){ pre=2;++cnt; } } front1=rear1=front2=rear2=0; for(int i=1;i<=n;i++){ du[i]=du1[i]; if(du[i]==0){ if(type[i]==1)que1[rear1++]=i; if(type[i]==2)que2[rear2++]=i; --du[i]; } } int cnt1=0; pre=2; while((front1!=rear1)||(front2!=rear2)){ int tf=0; while(front2!=rear2){ tf=1; int u=que2[front2++]; for(int i=head[u];i!=-1;i=e[i].next){ int v=e[i].to; du[v]--; if(du[v]==0){ if(type[v]==1)que1[rear1++]=v; if(type[v]==2)que2[rear2++]=v; du[v]--; } } } if(tf&&pre!=2){ pre=2;++cnt1; } tf=0; while(front1!=rear1){ tf=1; int u=que1[front1++]; for(int i=head[u];i!=-1;i=e[i].next){ int v=e[i].to; du[v]--; if(du[v]==0){ if(type[v]==1)que1[rear1++]=v; if(type[v]==2)que2[rear2++]=v; du[v]--; } } } if(tf&&pre!=1){ pre=1;++cnt1; } } return cnt<cnt1?cnt:cnt1;
} int main() { scanf("%d",&T); while(T--){ scanf("%d%d",&n,&m); init();memset(du,0,sizeof(du)); for(int i=1;i<=n;i++) Read(type[i]); for(int i=0,x,y;i<m;i++){ Read(x),Read(y); AddEdge(x,y);
++du[y]; } printf("%d\n",countt()); } return 0; }
|