题目链接(自用)
该题可以从实验室1开始或者从实验室2开始
用拓扑排序从实验室1开始跑一遍,再从实验室2开始跑一遍,求最小值就可以了
#include <map>
#include <set>
#include <cmath>
#include <deque>
#include <queue>
#include <stack>
#include <vector>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#define mod 1e9+7
#define INF 0x3f3f3f3f
#define read(x) scanf("%d",&x)
#define mem(a,b) memset(a,b,sizeof(a))
using namespace std;
typedef long long ll;
const int maxn=1e5+10;
const int maxm=1e6+10;
int in[maxn],map1[maxn],rein[maxn];
int n,m;
vector <int> G[maxm];
int main()
{
int t;
read(t);
while(t--)
{
scanf("%d %d",&n,&m);
int max1[2]={INF,INF};
mem(in,0);
for(int i=1;i<=n;++i)
{
read(map1[i]);
G[i].clear();
}
for(int i=1;i<=m;++i)
{
int u,v;
scanf("%d%d",&u,&v);
G[u].push_back(v);
in[v]++;
}
for(int i=1;i<=n;++i)
rein[i]=in[i];//点的入度复制用n
int tot=2;//tot用来查从实验室1和2开始,并且最终求最小值
int ans;
queue <int> que[2];//que[0]从实验室1开始,que[1]从实验室2开始
int cnt=0;
while(tot--)
{
cnt=0;
int now=tot;
for(int i=1;i<=n;++i)
in[i]=rein[i];
for(int i=1;i<=n;++i)
{
if(in[i]==0)
{
if(map1[i]==1)
que[0].push(i);
else
que[1].push(i);
}
}
do{
cnt++;
while(!que[now].empty())
{
int u=que[now].front();
que[now].pop();
for(int i=0;i<G[u].size();++i)
{
int v=G[u][i];
in[v]--;//删除u点,u连接的点入度减一
if(in[v]==0)
{
if(map1[v]==1)
{
que[0].push(v);
}
else
{
que[1].push(v);
}
}
}
}
now=1-now;//1变为0,0变为1转到下一个实验室去做
}while(!que[now].empty());
if(tot==1)
{
max1[0]=cnt;
}
if(tot==0)
{
max1[1]=cnt;
}
}
ans=min(max1[0],max1[1]);
printf("%d\n",ans-1);//cnt在每次开始循环的时候加了1所以最后要减1
}
return 0;
}