CF1679D

solution:二分&记忆化搜索

对于 \(ans\) ,容易想到随着 \(ans\) 的增大这张图能走的边就会更多,这是个单调增。

所以考虑二分。

对于 \(check\) 函数,先将可以走的边建成图,在对于图上每个点跑记忆化搜索,这样可以保证 \(check\) 时线性的,定义 \(f_i\) 为走到 \(i\) 时还能走多少个点。

显然他的儿子能到达的最远距离+到他这的距离 \(\geq\) k时就成立。

当第一遍搜时,就已经达到k,显然也是可行的。

对于环,我们考虑将搜到的点打标记,回溯的时候撤回标记,在搜的过程中如果搜到打了标记的,那就形成环。

总复杂度: \(O((n+m)~log~n)\)

code

//#pragma GCC optimize("Ofast")
//#pragma GCC optimize("inline")
#include<bits/stdc++.h>
#define re register
#define int long long
#define fep(i,l,r) for(re int i=l;i<=r;++i)
#define For(i,u) for(re int i=head[u];i;i=e[i].nxt)
#define feb(i,r,l) for(re int i=r;i>=l;--i)
using namespace std;
 
const int N = 2e6+5;
int n,m,k,head[N],tot,b[N],a[N],ans=-1,u[N],v[N],f[N]; bool vis[N];
struct Edge
{
	int v,nxt;
}e[N];

inline int read() { int s=0,w=1; char ch=getchar(); while(!(ch<='9'&&ch>='0')) {if(ch=='-') w=-1; ch=getchar();} while(ch<='9'&&ch>='0') {s=(s<<1)+(s<<3)+ch-'0'; ch=getchar();} return s*w; }
inline void write(int x) { if(x>=10) write(x/10); putchar(x%10+'0'); }
inline void print(int x) { if(x<0) putchar('-'),x=~(x-1); write(x); }

inline bool cmp(int d1,int d2) 
{
	return d1<d2; 
} 

inline void add(int u,int v)
{
	e[++tot]=(Edge){v,head[u]}; head[u]=tot;
}

inline bool dfs(int u,int p)
{
	if(p==k) return true;
	vis[u]=true;
	For(i,u)
	{
		if(vis[e[i].v]) return true;//形成了环 
		if(f[e[i].v])//已经深搜过了 
		{
			if(p+f[e[i].v]+1>=k) return true;//如果他的儿子能到达的最远距离+到他这的距离 >= k
		}
		else
		{
			bool flag=dfs(e[i].v,p+1);
			if(flag) return true;//成功了就返回 
		}
		f[u]=max(f[u],f[e[i].v]+1);//更新他能到达的最远距离 
	}
	vis[u]=false; return false;
}

inline bool check(int res)
{
	fep(i,1,n) head[i]=0,vis[i]=false,f[i]=0;
	while(tot) e[tot--]={0,0};
	fep(i,1,m)
	{
		if(res>=a[u[i]]&&res>=a[v[i]]) add(u[i],v[i]);
	}
	fep(i,1,n) if(a[i]<=res) if(dfs(i,1)) return true;
	return false;
}

signed main()
{
	n=read(),m=read(),k=read();
	fep(i,1,n) b[i]=a[i]=read();
	fep(i,1,m) u[i]=read(),v[i]=read();
	sort(b+1,b+1+n,cmp);
	int l=1,r=n;
	while(l<=r)
	{
		int mid=(l+r)>>1;
		if(check(b[mid])) ans=b[mid],r=mid-1;
		else l=mid+1;
	}
	print(ans);
	return 0;
}
posted @ 2022-05-14 20:00  starrylasky  阅读(33)  评论(0)    收藏  举报