传送门:https://codeforces.com/contest/1679/problem/D
思路:二分
可以通过二分答案si,对于judge的判断,可通过对于所有不大于si的边重新构图,然后先找图中是否有环,有则true,没有则从入度为0的点开始BFS找最长的路径即可
Code:
#include<iostream>
#include<algorithm>
#include<vector>
#include<queue>
using namespace std;
typedef long long LL;
typedef pair<int,int> pr;
const int MAX_N=2e5+5;
int n,m,T;
LL len;
int a[MAX_N];
pr d[MAX_N];
int in[MAX_N];
vector<int> G[MAX_N];
int boo[MAX_N];
bool DFS(int u)
{
bool res=false;
boo[u]=1;
for(auto v:G[u])
{
if(boo[v]==1||(!boo[v]&&DFS(v))){
res=true;
break;
}
}
boo[u]=2;
return res;
}
bool judge(int h)
{
bool res=false;
for(int i=1;i<=n;++i)
{
in[i]=0;
G[i].clear();
boo[i]=0;
}
int u,v;
for(int i=0;i<m;++i)
{
u=d[i].first;
v=d[i].second;
if(a[u]<=h&&a[v]<=h){
G[u].push_back(v);
++in[v];
}
}
for(int i=1;i<=n;++i)
{
if(!boo[i]&&in[i]&&DFS(i)){
res=true;
break;
}
}
if(res){
return res;
}
if(len>n){
return false;
}
queue<pr> Q;
for(int i=1;i<=n;++i)
{
if(!in[i]&&!G[i].empty()){
Q.push({i,1});
}
}
pr qi;
int s;
while(!Q.empty()){
qi=Q.front(); Q.pop();
u=qi.first;
s=qi.second;
for(auto v:G[u])
{
--in[v];
if(!in[v]){
Q.push({v,s+1});
if(s+1==len){
res=true;
break;
}
}
}
if(res){
break;
}
}
return res;
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0); cout.tie(0);
cin>>n>>m>>len;
int Min=1e9,Max=0;
for(int i=1;i<=n;++i)
{
cin>>a[i];
Min=min(Min,a[i]);
Max=max(Max,a[i]);
}
int u,v;
for(int i=0;i<m;++i)
{
cin>>u>>v;
d[i]={u,v};
}
int res=1e9;
int l=Min,r=Max,h;
if(len==1){
res=Min;
}else{
while(l<=r){
h=(l+r)/2;
if(judge(h)){
r=h-1;
}else{
l=h+1;
}
}
res=l;
if(l==Max+1){
res=-1;
}
}
cout<<res<<endl;
return 0;
}