如题,赛时过了赛后 FST WA on test 55。
思路是二分+拓扑。
#include<bits/stdc++.h>
#define int long long
using namespace std;
int n,m,k;
int a[200010];
struct edge
{
int u,v;
} s[200010];
int tot=0,var[200010],nxt[200010],head[200010];
void add(int u,int v)
{
var[++tot]=v;
nxt[tot]=head[u];
head[u]=tot;
}
int in[200010];
queue<int> q;
int maxx[200010];
bool check(int mid)
{
memset(maxx,0,sizeof(maxx));
tot=0; memset(head,0,sizeof(head));
memset(in,0,sizeof(in));
for(int i=1; i<=m; ++i)
{
if(a[s[i].u]<=mid && a[s[i].v]<=mid)
{
add(s[i].u,s[i].v);
++in[s[i].v];
}
}
int cnt=0;
for(int i=1; i<=n; ++i)
{
if(a[i]<=mid && !in[i])
{
++cnt;
q.push(i);
maxx[i]=1;
if(k==1) return 1;
}
}
while(!q.empty())
{
int frn=q.front(); q.pop();
for(int i=head[frn]; i; i=nxt[i])
{
--in[var[i]];
maxx[var[i]]=max(maxx[var[i]],maxx[frn]+1);
if(maxx[var[i]]>=k) return 1;
if(in[var[i]]==0)
{
q.push(var[i]);
}
}
}
for(int i=1; i<=n; ++i)
{
if(a[i]<=mid && in[i]) return 1;
}
return 0;
}
signed main()
{
cin>>n>>m>>k;
for(int i=1; i<=n; ++i)
{
cin>>a[i];
}
for(int i=1; i<=m; ++i)
{
cin>>s[i].u>>s[i].v;
}
int l=1,r=1e9,mid,ans=-1;
while(l<=r)
{
mid=(l+r)>>1;
if(check(mid))
{
ans=mid;
r=mid-1;
}
else l=mid+1;
}
cout<<ans;
return 0;
}
另外,这个我写出来的二分仿佛没有单调性,如果改变右端点会得到不同的答案。