Codeforces Round #791 (Div. 2) D

这篇博客讨论了一种求解有向图中,寻找长度为k-1的路径,使得路径上点权值之和最小的问题。通过二分答案结合深度优先搜索(DFS)策略进行解决,重点在于判断环路和寻找最长链。文章提供了详细的代码实现,包括检查环路的st数组使用,以及如何更新最长合法路径dp数组。
摘要由CSDN通过智能技术生成

D. Toss a Coin to Your Graph
题意:给定一个有向图,每次可以从任意节点出发找一条长度为k-1的路径,要求,求出路径上点权最大值最小是多少。

思路:首先我们不难想到这道题的基本思路是二分答案+DFS,根据图的特性重点放在设计DFS操作上

提示如下:
1.有向图,可以有环,所以当我们在DFS的过程中遇到一个合法环就可以直接判为合法路径(一下子用完k步),所以需要判环操作

2.普通在无环情况下我们要找的无疑是一条链,所以还需要统计从某个节点出发的最长链

3.在选择节点走时必要条件是选择的这个节点的权值不能大于我们想要的二分值

DFS之后判断是否存在合法路径,也就是是否存在以某个点为起点的合法路径长度要>=k

ACcode

#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N=2e5+10;
struct node
{
    int nex,to;
};
node edge[N];
int head[N],tot;
bool vis[N];//判访问
int w[N];//权值
int n,m,k;
int dp[N];//从i开始的最长合法路径

bool st[N];//判环
void add(int from,int to)
{
	edge[++tot].nex=head[from];
	edge[tot].to=to;
	head[from]=tot;
}
void dfs(int now,int x)
{
	st[now]=true;
	vis[now]=true;
	dp[now]=1;
	for(int i=head[now];i;i=edge[i].nex)
	{
		int to=edge[i].to;
		if(w[to]<=x)
		{
			if(st[to])//又访问已经经过的节点,说明形成了环
            {
                dp[now]=k;
                break;
            }
			else
			{
				if(!vis[to])//没有走过的节点继续选择
                {
                    dfs(to,x);
                }
				dp[now]=max(dp[now],dp[to]+1);
			}
		}
	}
	st[now]=false;//
}
bool check(int x)
{
	memset(vis,false,sizeof(vis));
	for(int i=1;i<=n;i++)
        if(!vis[i]&&w[i]<=x)
            dfs(i,x);
	for(int i=1;i<=n;i++)
        if(vis[i]&&dp[i]>=k)
           return true;
	return false;
}
signed main()
{
    /*cin.tie(0);
    cout.tie(0);
    ios::sync_with_stdio(0);*/
	scanf("%lld%lld%lld",&n,&m,&k);
	for(int i=1;i<=n;i++)
	{
		scanf("%lld",&w[i]);
	}
	while(m--)
	{
		int a,b;
		scanf("%lld%lld",&a,&b);
		add(a,b);
	}
	int l=1,r=1e9+1;
	while(l<=r)
	{
		int mid=(l+r)>>1;
		if(check(mid))
        {
            r=mid-1;
        }
		else
        {
            l=mid+1;
        }
	}
	if(r==1e9+1)
    {
        cout<<-1<<'\n';
    }
	else
    {
        cout<<l<<'\n';
    }
	return 0;
}

关于st数组的判环操作

我们在真正形成一个环的时候显然用不到外层的st[now]=false操作

但是在不能形成一个环的时候,假设一个点的入度为2出度为0,设想没有st[now]=false操作的话会怎样。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值