动态规划——用带权的有向图描述状态的转移

这篇具有很好参考价值的文章主要介绍了动态规划——用带权的有向图描述状态的转移。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

前言

此文章的作用:教会读者用简单、快速、稳定的方法推出线性DP的转移方程。

笔者希望通过一些题教会读者做所有线性DP的方法,而不是只教会读者这些题的解法。

先看题:一本通 大盗阿福

我们发现:店铺越多,可以偷的店铺就越多,能得到的现金就越多。

举例:如果只有一家店铺,你就只能偷第一家,只能拿到第一家店铺的现金。但如果有三家店铺,你就可以偷第一和第三家,同时拿到第一家和第三家的现金。

这说明:(最多可以得到的现金)是(店铺数量)的函数

这又说明表示状态中肯定有一个维度是店铺数量。

所以暂时 d p i dp_i dpi :偷前 i i i 家店铺的最大值。

再次观察发现对于每个店铺只有偷和不偷两个选择。

所以设 d p i , [ 0 / 1 ] dp_{i,[0/1]} dpi,[0/1]:对于前 i i i 家店铺, [ [ [ 不偷 ( 0 ) (0) (0) / / / ( 0 ) (0) (0) ] ] ] i i i 家店铺的最大值。

有了状态,就要推状态转移方程了。

第一种画法

回归标题,我们用带权的有向图描述状态的转移,其中点表示状态,边表示状态的转移增量

先画出有哪些状态,如图:
有向图 利润,动态规划,算法,题解,动态规划,算法,c++

先考虑 d p i , 0 dp_{i,0} dpi,0 可以由那些状态转移过来

  1. d p i , 0 dp_{i,0} dpi,0 是否可以由 d p i − 1 , 0 dp_{i-1,0} dpi1,0 转移过来?两家店铺都没有偷,不会触发警报,可以转移。因为并当前状态没有选择偷第 i i i 个店铺,所以转移增量为 0 0 0 。所以,有一条边权为 0 0 0 的边从 d p i − 1 , 0 dp_{i-1,0} dpi1,0 连向 d p i , 0 dp_{i,0} dpi,0(边权为 0 0 0 的默认不在图上标出边权)。

现在的图就变成了这样:

有向图 利润,动态规划,算法,题解,动态规划,算法,c++

  1. d p i , 0 dp_{i,0} dpi,0 是否可以由 d p i − 1 , 1 dp_{i-1,1} dpi1,1 转移过来?只偷上一家店铺,不偷当前店铺,没有同时偷相邻的两家,不会触发警报,所以可以转移。同样因为并当前状态没有选择偷第 i i i 个店铺,所以转移增量为 0 0 0 。所以,有一条边权为 0 0 0 的边从 d p i − 1 , 0 dp_{i-1,0} dpi1,0 连向 d p i , 0 dp_{i,0} dpi,0(边权为 0 0 0 的默认不在图上标出边权)。

现在的图就变成了这样:

有向图 利润,动态规划,算法,题解,动态规划,算法,c++

现在考虑 d p i , 1 dp_{i,1} dpi,1 可以由哪些状态转移过来

  1. d p i , 1 dp_{i,1} dpi,1 是否可以由 d p i − 1 , 0 dp_{i-1,0} dpi1,0 转移过来?只偷当前店铺,不偷上一家店铺,没有同时偷相邻的两家,不会触发警报,所以可以转移,因为并当前状态选择偷第 i i i 个店铺,所以转移增量为 w i w_i wi ,所以,有一条边权为 w i w_i wi 的边从 d p i − 1 , 0 dp_{i-1,0} dpi1,0 连向 d p i , 0 dp_{i,0} dpi,0

现在的图就变成了这样:

有向图 利润,动态规划,算法,题解,动态规划,算法,c++

  1. d p i , 1 dp_{i,1} dpi,1 是否可以由 d p i − 1 , 1 dp_{i-1,1} dpi1,1 转移过来?即偷了上一家店铺,也偷了当前店铺,同时偷了相邻的两家,会触发警报,所以不能转移。

第二种画法

这道题对于每个店铺都有 [ [ [ 不偷 ( 0 ) (0) (0) / / / ( 1 ) (1) (1) ] ] ] 两种状态,如图:

有向图 利润,动态规划,算法,题解,动态规划,算法,c++

  1. 状态 0 0 0 可以由状态 0 0 0 转移过来,转移增量为 0 0 0

有向图 利润,动态规划,算法,题解,动态规划,算法,c++

  1. 状态 0 0 0 可以由状态 1 1 1 转移过来,转移增量为 0 0 0

有向图 利润,动态规划,算法,题解,动态规划,算法,c++

  1. 状态 1 1 1 可以由状态 0 0 0 转移过来,转移增量为 w i w_i wi

有向图 利润,动态规划,算法,题解,动态规划,算法,c++

  1. 状态 1 1 1 不可以由状态 1 1 1 转移过来。

那么,看着图就很容易写出状态转移方程了。

d p i , 0 = max ⁡ ( d p i − 1 , 0 , d p i − 1 , 1 ) dp_{i,0}=\max(dp_{i-1,0},dp_{i-1,1}) dpi,0=max(dpi1,0,dpi1,1)
d p i , 1 = d p i − 1 , 0 dp_{i,1}=dp_{i-1,0} dpi,1=dpi1,0

代码

#include<bits/stdc++.h>
#define ll long long
using namespace std;
ll n,w[1000005],dp[1000005][2];
void work(){
	cin>>n;
	for(ll i=1;i<=n;i++)cin>>w[i];
	for(ll i=0;i<=n;i++)dp[i][0]=dp[i][1]=0;
	for(ll i=1;i<=n;i++){
		dp[i][0]=max(dp[i-1][0],dp[i-1][1]);
		dp[i][1]=dp[i-1][0]+w[i];
	}
	cout<<max(dp[n][0],dp[n][1])<<endl;
}
signed main(){
	ios::sync_with_stdio(false);
	ll T;cin>>T;
	while(T--)work();
	return 0;
}

再次强调声明,题目虽然不难,可能有人不画图也能想出状态转移方程,我希望教会读者的是这做一类题的方法,而不只是这一道题的解法。

再看一道题:Acwing 股票买卖

我们发现:天数越多,可以买卖的股票就越多,能得到的利润就越多。

这说明:(最多能得到的利润)是(天数)的函数

这又说明表示状态中肯定有一个维度是股票数量。

所以暂时 d p i dp_i dpi :对于前 i i i 天 ,可以获得的的最大值。

再次观察发现对于每天只有持有股票和不持有股票两个选择。

所以设 d p i , [ 0 / 1 ] dp_{i,[0/1]} dpi,[0/1] :对于前 i i i 天,第 i i i [ [ [ 未持有(0) / / / 持有(1) ] ] ] 股票的最利润。

第一种画法

先把有哪些状态画出来:

有向图 利润,动态规划,算法,题解,动态规划,算法,c++

先考虑 d p i , 0 dp_{i,0} dpi,0 可以由哪些状态转移过来。

  1. d p i , 0 dp_{i,0} dpi,0 可以由 d p i − 1 , 0 dp_{i-1,0} dpi1,0 转移过来。因为都是不持有股票的状态,没有买卖,所以转移增量为 0 0 0

如图:

有向图 利润,动态规划,算法,题解,动态规划,算法,c++

  1. d p i − 1 , 0 dp_{i-1,0} dpi1,0 可以由 d p i − 1 , 1 dp_{i-1,1} dpi1,1 转移过来,昨天有票,但今天没票了,这说明当天卖出了股票,卖出股票可以赚钱。所以转移增量为 w i w_i wi

有向图 利润,动态规划,算法,题解,动态规划,算法,c++

再考虑 d p i , 1 dp_{i,1} dpi,1 可以由哪些状态转移过来。

  1. d p i , 1 dp_{i,1} dpi,1 可以由 d p i − 1 , 0 dp_{i-1,0} dpi1,0 转移过来,昨天不持有股票,今天持有股票,说明今天买入了股票,买入股票需要花钱,所以转移增量为 − w i -w_i wi

有向图 利润,动态规划,算法,题解,动态规划,算法,c++

  1. d p i , 1 dp_{i,1} dpi,1 可以由 d p i − 1 , 1 dp_{i-1,1} dpi1,1 转移过来。因为都是持有股票的状态,没有买卖,所以转移增量为 0 0 0

有向图 利润,动态规划,算法,题解,动态规划,算法,c++

第二种画法

先画出有哪些状态:

有向图 利润,动态规划,算法,题解,动态规划,算法,c++

  1. 状态 0 0 0 可以由状态 0 0 0 转移过来,转移增量为 0 0 0

有向图 利润,动态规划,算法,题解,动态规划,算法,c++

  1. 状态 0 0 0 可以由状态 1 1 1 转移过来,所以转移增量为 w i w_i wi

有向图 利润,动态规划,算法,题解,动态规划,算法,c++
3. 状态 1 1 1 可以由状态 1 1 1 转移过来,转移增量为 0 0 0

有向图 利润,动态规划,算法,题解,动态规划,算法,c++

  1. 状态 1 1 1 可以由状态 0 0 0 转移过来,所以转移增量为 − w i -w_i wi

有向图 利润,动态规划,算法,题解,动态规划,算法,c++

看着图就很容易写出状态转移方程了。

d p i , 0 = max ⁡ ( d p i − 1 , 0 , d p i − 1 , 1 + w i ) dp_{i,0}=\max(dp_{i-1,0},dp_{i-1,1}+w_i) dpi,0=max(dpi1,0,dpi1,1+wi)
d p i , 1 = max ⁡ ( d p i − 1 , 0 − w i , d p i − 1 , 1 ) dp_{i,1}=\max(dp_{i-1,0}-w_i,dp_{i-1,1}) dpi,1=max(dpi1,0wi,dpi1,1)

在这里再教大家一个确定状态转移方程边界值的方法。

1. 1. 1. 在哪赋边界值?

    ~~~     需要处理的值域范围的最小值往前推一个单位。

    ~~~     就拿这道题举例,我们需要处理的值域范围是 1 1 1~ n n n,那么就给第 0 0 0 天附上边界值。

2. 2. 2. 赋什么值?

    ~~~     如果该状态是非法的,就赋一个极大值或极小值,因为一个状态不会通过一个非法的状态转移过来。

    ~~~     如果该状态是合法的,就赋一个有限的值(通常是 0 0 0)。

    ~~~     还是拿这道题举例举例, d p 0 , 0 dp_{0,0} dp0,0 状态是合法的,附上 0 0 0 d p 0 , 1 dp_{0,1} dp0,1 状态是非法的,赋上极小值。

代码

#include<bits/stdc++.h>
#define ll long long
#define INF 0x3f3f3f3f3f3f3f
using namespace std;
ll n,dp[100005][2],w[100005];
signed main(){
	ios::sync_with_stdio(false);
	cin>>n;
	for(ll i=1;i<=n;i++)cin>>w[i];
	dp[0][1]=-INF;dp[0][0]=0;
	for(ll i=1;i<=n;i++){
		dp[i][0]=max(dp[i-1][0],dp[i-1][1]+w[i]);
		dp[i][1]=max(dp[i-1][0]-w[i],dp[i-1][1]);
	}
	cout<<dp[n][0]<<endl;
	return 0;
}

再来看看股票买卖的升级版 Acwing 股票买卖(k笔交易)

发现这道题与上一题的区别就是多了一个限制:只能有最多 k k k 笔交易。

那我们在状态的表示上是不是就要多一维:当前正在进行第几笔交易。

所以设 d p i , j , [ 0 / 1 ] dp_{i,j,[0/1]} dpi,j,[0/1]:对于前 i i i 天,第 j j j 笔交易 [ [ [ 未持有 ( 0 ) (0) (0) / / / 持有 ( 1 ) (1) (1) ] ] ] 股票的最大利润。

先看第一种画法

先画出有哪些状态

有向图 利润,动态规划,算法,题解,动态规划,算法,c++

发现这样画的话过于复杂了,我们需要简化一下。如下图:

有向图 利润,动态规划,算法,题解,动态规划,算法,c++

先考虑 d p i , j , 0 dp_{i,j,0} dpi,j,0 可以由哪些状态转移过来。

  1. d p i , j , 0 dp_{i,j,0} dpi,j,0 可以由 d p i − 1 , j − 1 , 0 dp_{i-1,j-1,0} dpi1,j1,0 转移过来吗?不可以,因为两种状态都没有持有股票,也就是没有进行交易,因为没有进行交易,所以当前这笔交易不能从上一笔交易转移过来。

  2. d p i , j , 0 dp_{i,j,0} dpi,j,0 可以由 d p i − 1 , j − 1 , 1 dp_{i-1,j-1,1} dpi1,j1,1 转移过来吗?可以,昨天持有股票,今天不持有股票,说明卖出了一张股票,所以转移增量为 w i w_i wi

有向图 利润,动态规划,算法,题解,动态规划,算法,c++

  1. d p i , j , 0 dp_{i,j,0} dpi,j,0 可以由 d p i − 1 , j , 0 dp_{i-1,j,0} dpi1,j,0 转移过来吗?可以,因为两种状态都没有持有股票,也就是没有进行交易,所以当前这笔交易可以从昨天的同一笔交易转移过来。因为没有买卖,所以转移增量为 0 0 0

有向图 利润,动态规划,算法,题解,动态规划,算法,c++

  1. d p i , j , 0 dp_{i,j,0} dpi,j,0 可以由 d p i − 1 , j , 1 dp_{i-1,j,1} dpi1,j,1 转移过来吗?当然不可以,你买了股票不可能退回去吧。

再来考虑 d p i , j , 1 dp_{i,j,1} dpi,j,1 可以由哪些状态转移过来。

  1. d p i , j , 1 dp_{i,j,1} dpi,j,1 可以由 d p i − 1 , j − 1 , 0 dp_{i-1,j-1,0} dpi1,j1,0 转移过来吗?不可以,因为不能直接跳过上一笔交易的持有股票状态和当前这一笔交易的未持有股票状态。

  2. d p i , j , 1 dp_{i,j,1} dpi,j,1 可以由 d p i − 1 , j − 1 , 1 dp_{i-1,j-1,1} dpi1,j1,1 转移过来吗?不可以,因为上一笔交易股票必须要先买了才能买当前股票(题目要求)。

  3. d p i , j , 1 dp_{i,j,1} dpi,j,1 可以由 d p i − 1 , j , 0 dp_{i-1,j,0} dpi1,j,0 转移过来吗?可以,从这一笔交易不持有股票到持有股票,说明买入了股票,买股票要花钱,所以转移增量为 − w i -w_i wi

有向图 利润,动态规划,算法,题解,动态规划,算法,c++

  1. d p i , j , 1 dp_{i,j,1} dpi,j,1 可以由 d p i − 1 , j , 1 dp_{i-1,j,1} dpi1,j,1 转移过来吗?可以,因为两种状态都持有股票,也就是没有进行交易,所以当前这笔交易可以从昨天的同一笔交易转移过来。因为没有买卖,所以转移增量为 0 0 0

有向图 利润,动态规划,算法,题解,动态规划,算法,c++

再来看第二种画法

每天的每笔交易只有两个状态 [ [ [ 未持有股票 ( 0 ) (0) (0) / / / 持有股票 ( 1 ) (1) (1) ] ] ]

有向图 利润,动态规划,算法,题解,动态规划,算法,c++

先考虑状态 0 0 0 可以由哪些状态转移过来。

  1. 状态 0 0 0 可以由昨天的同一笔交易的状态 0 0 0 转移过来,转移增量为 0 0 0

有向图 利润,动态规划,算法,题解,动态规划,算法,c++

  1. 状态 0 0 0 可以由昨天的上一笔交易的状态 1 1 1 转移过来,转移增量为 w i w_i wi

有向图 利润,动态规划,算法,题解,动态规划,算法,c++

再虑状态 1 1 1 可以由哪些状态转移过来。

  1. 状态 1 1 1 可以由昨天的同一笔交易的状态 1 1 1 转移过来,转移增量为 0 0 0

有向图 利润,动态规划,算法,题解,动态规划,算法,c++

  1. 状态 1 1 1 可以由昨天的同一笔交易的状态 0 0 0 转移过来,转移增量为 − w i -w_i wi

有向图 利润,动态规划,算法,题解,动态规划,算法,c++

接下来就是看着图推状态转移方程

d p i , j , 0 = max ⁡ ( d p i − 1 , j − 1 , 1 + w i , d p i − 1 , j , 0 ) dp_{i,j,0}=\max(dp_{i-1,j-1,1}+w_i,dp_{i-1,j,0}) dpi,j,0=max(dpi1,j1,1+wi,dpi1,j,0)
d p i , j , 1 = max ⁡ ( d p i − 1 , j , 0 − w i , d p i − 1 , j , 1 ) dp_{i,j,1}=\max(dp_{i-1,j,0}-w_i,dp_{i-1,j,1}) dpi,j,1=max(dpi1,j,0wi,dpi1,j,1)

给代码赋初值的方法和上一道题一样,这里再拿这道题举个例子

1. 1. 1. 在哪赋边界值?

    ~~~     我们需要处理的值域范围是 1 1 1~ n n n,那么就给第 0 0 0 天附上边界值。

2. 2. 2. 赋什么值?

    ~~~     d p 0 , ( 1 ≤ j ≤ k ) , 0 dp_{0,(1\le j\le k),0} dp0,(1jk),0 状态是合法的,附上 0 0 0 d p 0 , ( 1 ≤ j ≤ k ) , 1 dp_{0,(1\le j\le k),1} dp0,(1jk),1 状态是非法的,赋上极小值。

注意:因为我们要求的是做完 k k k 笔交易后的利润,所以要在代码中的 k k k 加上 1 1 1

还有一件事:这道题卡空间,需要滚动数组优化。为了方便读者理解,我会放两版代码,一版是滚动数组优化前的,一版是滚动数组优化后的。

代码

滚动数组优化前的:

#include<bits/stdc++.h>
#define ll long long
#define INF 0x3f3f3f3f3f3f3f
using namespace std;
ll n,k,w[100005],dp[100005][105][2];
signed main(){
	ios::sync_with_stdio(false);
	cin>>n>>k;k++;
	for(ll i=1;i<=n;i++)cin>>w[i];
	for(ll j=1;j<=k;j++)dp[0][j][1]=-INF;
	for(ll i=0;i<=n;i++)dp[i][0][1]=-INF;
	for(ll i=1;i<=n;i++){
		for(ll j=1;j<=k;j++){
			dp[i][j][0]=max(dp[i-1][j][0],dp[i-1][j-1][1]+w[i]);
			dp[i][j][1]=max(dp[i-1][j][1],dp[i-1][j][0]-w[i]);
		}
	}
	cout<<dp[n][k][0];
	return 0;
}

滚动数组优化后的:

#include<bits/stdc++.h>
#define ll long long
#define INF 0x3f3f3f3f3f3f3f
using namespace std;
ll n,k,w[100005],dp[2][105][2];
signed main(){
	ios::sync_with_stdio(false);
	cin>>n>>k;k++;
	for(ll i=1;i<=n;i++)cin>>w[i];
	for(ll j=1;j<=k;j++)dp[0][j][1]=-INF;
	for(ll i=1;i<=n;i++){
		dp[0][0][1]=-INF;
		for(ll j=1;j<=k;j++){
			dp[1][j][0]=max(dp[0][j][0],dp[0][j-1][1]+w[i]);
			dp[1][j][1]=max(dp[0][j][1],dp[0][j][0]-w[i]);
		}
		for(ll j=1;j<=k;j++){
			dp[0][j][0]=dp[1][j][0];
			dp[0][j][1]=dp[1][j][1];
		}
	}
	cout<<dp[1][k][0];
	return 0;g
}

再来看最后一道题

股票买卖的另一种升级版 Acwing [股票买卖(含冷冻期)]

这道题原题面不知道为什么打不开,但是我们可以在LeetCode上看题面。

发现这道题与股票买卖的差别就是卖完股票后不能立刻买股票,那我们往前多考虑一位就可以了。

还是设 d p i , [ 0 / 1 ] dp_{i,[0/1]} dpi,[0/1] 为对于前 i i i 天,第 i i i [ [ [ 未持有股票 ( 0 ) (0) (0) / / / 持有股票 ( 1 ) (1) (1) ] ] ] 能获得的最大利润。

画法一

先画出有哪些状态。

有向图 利润,动态规划,算法,题解,动态规划,算法,c++

d p i , 0 dp_{i,0} dpi,0 可以由 d p i − 1 , 0 dp_{i-1,0} dpi1,0 d p i − 1 , 1 dp_{i-1,1} dpi1,1 转移过来,之前已经讲过,这里就不赘述了。

有向图 利润,动态规划,算法,题解,动态规划,算法,c++

d p i , 1 dp_{i,1} dpi,1 可以由 d p i − 1 , 1 dp_{i-1,1} dpi1,1 转移过来,同样上面讲过, d p i , 1 dp_{i,1} dpi,1 要由 d p i − 2 , 0 dp_{i-2,0} dpi2,0 转移,因为至少要隔一天。

有向图 利润,动态规划,算法,题解,动态规划,算法,c++

画法二

过程大家都很熟悉了,直接上最终版。

有向图 利润,动态规划,算法,题解,动态规划,算法,c++

状态转移方程:

d p i , 0 = max ⁡ ( d p i − 1 , 0 , d p i − 1 , 1 + w i ) dp_{i,0}=\max(dp_{i-1,0},dp_{i-1,1}+w_i) dpi,0=max(dpi1,0,dpi1,1+wi)
d p i , 1 = max ⁡ ( d p i − 2 , 0 − w i , d p i − 1 , 1 ) dp_{i,1}=\max(dp_{i-2,0}-w_i,dp_{i-1,1}) dpi,1=max(dpi2,0wi,dpi1,1)

这道题因为原题面有问题我就不放代码了,大家理解了就行。

总结: 用带权的有向图描述状态的转移

如果你还有问题,可以私信我,如果是在工作日,我会尽量在 12 12 12 小时内回复。

比起点赞收藏和关注,我更希望你们可以把不懂的地方告诉我。

正文结束

附:

这个方法我是看了这位老师的讲解学会的。

废话

啊啊啊啊啊啊啊啊啊啊啊终于写完了啊啊啊啊啊啊啊。

为了大家有一个更流畅的阅读体验,还特意压缩了图片大小(虽然可能还是有点卡)

要是A股可以这样,我还刷什么题呀。

作为一个正在准备NOIP的初三信竞生,时间真的不多,所以我要断更一周。文章来源地址https://www.toymoban.com/news/detail-854850.html

到了这里,关于动态规划——用带权的有向图描述状态的转移的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 2023-8-29 有向图的拓扑排序

    题目链接:有向图的拓扑排序

    2024年02月11日
    浏览(37)
  • 有向图的强连通分量算法

    有向图的强连通分量算法 强连通分量定义 在有向图中,某个子集中的顶点可以直接或者间接互相可达,那么这个子集就是此有向图的一个强连通分量,值得注意的是,一旦某个节点划分为特定的强连通分量后,此顶点不能在其它子树中重复使用,隐含了图的遍历过程和极大

    2024年02月06日
    浏览(84)
  • 真题详解(有向图)-软件设计(六十二)

    真题详解(极限编程)-软件设计(六十一) https://blog.csdn.net/ke1ying/article/details/130435971 CMM指软件成熟度模型,一般1级成熟度最低,5级成熟度最高,采用更高级的CMM模型可以提高软件质量。 初始:杂乱无章。 可重复级:建立基本的项目管理过程和跟踪费用项。 已定义(确定)

    2024年02月01日
    浏览(63)
  • 2023-04-09 有向图及相关算法

    有向图的的应用场景 社交网络中的关注 互联网连接 程序模块的引用 任务调度 学习计划 食物链 论文引用 无向图是特殊的有向图,即每条边都是双向的 改进Graph和WeightedGraph类使之支持有向图 Graph类的改动 WeightedGraph类的改动 有些问题,在有向图中不存在,或者我们通常不考

    2024年02月05日
    浏览(46)
  • 有向图的邻接表和邻接矩阵

    有向图的邻接表是一种常用的表示方法,用于表示图中各个节点之间的关系。在有向图中,每条边都有一个方向,因此邻接表中的每个节点记录了该节点指向的其他节点。 具体来说,有向图的邻接表由一个由节点和它们的邻居节点列表组成的集合构成。对于每个节点,邻接表

    2024年02月22日
    浏览(41)
  • 搜索与图论-有向图的拓扑序列

    有向图的拓扑序列就是图的广度优先遍历的一个应用。 若一个由图中所有点构成的序列 A 满足:对于图中的每条边 (x,y),x 在 A 中都出现在 y 之前,则称 A 是该图的一个 拓扑序列 。(起点在终点的前面) 拓扑序列是针对有向图,无向图是没有拓扑序列的。 有向无环图一定是

    2024年02月01日
    浏览(44)
  • 使用颜色检测有向图中的循环

    给定一个有向图,检查该图是否包含循环。如果给定的图形至少包含一个循环,您的函数应返回 true,否则返回 false。 例子:   输入:  n = 4, e = 6  0 - 1, 0 - 2, 1 - 2, 2 - 0, 2 - 3, 3 - 3  输出: 是  解释:    

    2024年02月03日
    浏览(45)
  • 二十一、搜索与图论——拓扑序列(有向图)

    拓扑序列定义: 若一个由图中所有点构成的序列 A满足:对于图中的每条边 (x,y),x在 A中都出现在 y之前,则称 A是该图的一个拓扑序列。 人话: 始终满足每条边的起点在终点前面,从前指向后。 注意:如果在有向图中构成一个环,则必定无法构成拓扑结构,也可以证明有向

    2024年02月04日
    浏览(54)
  • 哪些方法可以判断出一个有向图是否有环

    使用 深度优先遍历 ,若从有向图上的某个顶点u出发,在 DFS(u)结束之前出现一条从顶点v到u的边,由于v在生成树上是u的子孙,则图中必定存在包含u和v的环,因此深度优先遍历可以检测一个有向图是否有环。 拓扑排序 时,当某顶点不为任何边的头时才能加入序列,存在环时环中的

    2024年02月12日
    浏览(47)
  • 教学计划编制问题(数据结构 有向图 拓扑排序)

     本文对以下教学计划编制问题的解决作出实现,主要使用c语言(带一点cpp),开发环境为codeblocks 17.12,希望对各位读者有所帮助。(源码和数据文件可在主页获取,同时还有使用视频文件压缩包,数据文件需要和exe在同一目录下,结合某读者的意见同时放到github了 ) 地址如下

    2024年02月09日
    浏览(56)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包