国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

拓?fù)渑判蛟斀猓ò惴ㄔ韴D解、算法實(shí)現(xiàn)過程詳解、算法例題變式全面講解等)

這篇具有很好參考價(jià)值的文章主要介紹了拓?fù)渑判蛟斀猓ò惴ㄔ韴D解、算法實(shí)現(xiàn)過程詳解、算法例題變式全面講解等)。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問。

前置知識(shí)

有向無環(huán)圖

在圖論中,如果一個(gè)有向圖無法從某個(gè)頂點(diǎn)出發(fā)經(jīng)過若干條邊回到該點(diǎn),則這個(gè)圖是一個(gè)有向無環(huán)圖(DAG圖)。
如圖所示。
拓?fù)渑判?圖論初步,算法,數(shù)據(jù)結(jié)構(gòu),圖論,c++

入度

對(duì)于一個(gè)有向圖,若x點(diǎn)指向y點(diǎn),則稱x點(diǎn)為y點(diǎn)的入度。

出度

對(duì)于一個(gè)有向圖,若x點(diǎn)指向y點(diǎn),則稱y點(diǎn)為x點(diǎn)的出度。

隊(duì)列

隊(duì)列是一種特殊的線性表,特殊之處在于它只允許在表的前端(front)進(jìn)行刪除操作,而在表的后端(rear)進(jìn)行插入操作,和棧一樣,隊(duì)列是一種操作受限制的線性表。進(jìn)行插入操作的端稱為隊(duì)尾,進(jìn)行刪除操作的端稱為隊(duì)頭。

我們可以用雙指針標(biāo)記一下,通過front指針與rear指針,對(duì)隊(duì)頭和隊(duì)尾進(jìn)行標(biāo)記,然后只允許在front、rear指針的位置進(jìn)行增刪改查,那么這樣便實(shí)現(xiàn)了對(duì)數(shù)組的受限。這是一種運(yùn)用數(shù)組的數(shù)據(jù)結(jié)構(gòu)對(duì)隊(duì)列的模擬。初學(xué)者建議先用這種方式熟悉隊(duì)列。

具體操作:

/*
    通常將front賦值為0,rear賦值為-1
    方便后續(xù)進(jìn)隊(duì)、出隊(duì)以及取隊(duì)首元素
 */
int a[100], front=0, rear=-1;

// 進(jìn)隊(duì)
a[++rear] = 10;

// 出隊(duì)
front++

// 取隊(duì)首元素
a[front]

// 取隊(duì)尾元素
a[rear]

// 判斷是否為空隊(duì)
if(front > rear)
    cout << "該隊(duì)列為空隊(duì)";

不過,到了后期,為了節(jié)省時(shí)間,我們可以直接用c++自帶的STL容器來完成操作。

具體操作如下:

// 導(dǎo)入queue包
#include<queue>

// 申明一個(gè)queue對(duì)象
// 填入你想裝填的數(shù)據(jù)類型
queue<int> qu;

// 進(jìn)隊(duì)
int a = 10;
qu.push(a);

// 出隊(duì),無返回值
qu.pop();

// 取隊(duì)首元素
int front = qu.front();

概述

今天我們來學(xué)拓?fù)渑判?/strong>
什么是拓?fù)渑判蚰兀?br>百度百科這樣說:

對(duì)一個(gè)有向無環(huán)圖(Directed Acyclic Graph簡稱DAG)G進(jìn)行拓?fù)渑判?,是將G中所有頂點(diǎn)排成一個(gè)線性序列,使得圖中任意一對(duì)頂點(diǎn)u和v,若邊<u,v>∈E(G),則u在線性序列中出現(xiàn)在v之前。通常,這樣的線性序列稱為滿足拓?fù)浯涡?Topological Order)的序列,簡稱拓?fù)湫蛄小:唵蔚恼f,由某個(gè)集合上的一個(gè)偏序得到該集合上的一個(gè)全序,這個(gè)操作稱之為拓?fù)渑判颉?/p>

什么意思呢?

俗話說的好:

實(shí)踐是真理的試金石

那么,就讓我們舉一個(gè)例子吧!
如圖,1、2、3、4、5幾個(gè)點(diǎn)組成了一個(gè)圖。

拓?fù)渑判?圖論初步,算法,數(shù)據(jù)結(jié)構(gòu),圖論,c++
那么,1,2,4,3,6,5或1,2,4,3,5,6就是它的拓?fù)湫?/strong>

但是,這是如何實(shí)現(xiàn)的呢?請(qǐng)看下面的算法原理。

算法原理

下面我將使用圖文結(jié)合的方式演示拓?fù)渑判虻乃惴ㄔ怼?/p>

還是上面那張圖。
拓?fù)渑判?圖論初步,算法,數(shù)據(jù)結(jié)構(gòu),圖論,c++
首先,將入度為0的點(diǎn)入隊(duì)。上圖中是點(diǎn)1。

拓?fù)渑判?圖論初步,算法,數(shù)據(jù)結(jié)構(gòu),圖論,c++
然后,用寬搜遍歷隊(duì)列。
對(duì)每個(gè)點(diǎn)的每輪遍歷步驟如下:

  • 將這個(gè)點(diǎn)出隊(duì),并加入拓?fù)鋽?shù)組中
  • 遍歷這個(gè)點(diǎn)的所有出度
  • 將其出度點(diǎn)的入度數(shù)量減少一
  • 如果其出度點(diǎn)入度為0,入隊(duì)

那么,一輪下來,就變成這樣子了:
拓?fù)渑判?圖論初步,算法,數(shù)據(jù)結(jié)構(gòu),圖論,c++
以此類推。

遍歷到點(diǎn)3時(shí),是這樣的:
拓?fù)渑判?圖論初步,算法,數(shù)據(jù)結(jié)構(gòu),圖論,c++
……

然后,就沒有然后了,一切結(jié)束。
拓?fù)渑判?圖論初步,算法,數(shù)據(jù)結(jié)構(gòu),圖論,c++
如圖所示,其拓?fù)湫驗(yàn)?,2,4,3,5,6。當(dāng)然,也可以是1,2,4,3,6,5。

算法實(shí)現(xiàn)

這可以變?yōu)橐韵碌膯栴}。我稱為拓?fù)渑判蛟獑栴}。

給你一個(gè)有向無環(huán)圖,請(qǐng)輸出它的拓?fù)湫颍╩條有向邊,n個(gè)結(jié)點(diǎn))

建圖(鄰接表存圖)

首先,我們要建圖
這里采用鄰接表建圖。

鄰接表是什么?
以點(diǎn)為一個(gè)結(jié)點(diǎn),用其鄰接點(diǎn)建表

怎么這么朦朧?好吧,偷懶了,自己查百度……

看到這里,就默認(rèn)你會(huì)了建圖操作。那么,放一下代碼。
(此處設(shè)定為m條有向邊)

for(int i=1;i<=m;i++)
{
	int x,y;
	scanf("%d%d",&x,&y);
	rd[y]++;
	e[x].push_back(y);
}

rd[y]++ 是什么意思?請(qǐng)往后看。

入隊(duì)

上面提到,首先,將入度為0的點(diǎn)入隊(duì)。
那么,我們就遍歷一遍n個(gè)點(diǎn),當(dāng)遇到入度為0的點(diǎn)時(shí),入隊(duì)。

如何判斷入度為0?

這時(shí)前面的 rd數(shù)組 就有用了。它是用于統(tǒng)計(jì)入度數(shù)的。
而前面為何是rd[y]++?
因?yàn)槭?x指向y,因此y入度數(shù)加1

入隊(duì)操作

非常簡單!這里為了省力,用了STL容器
只需要**q.push(i)**一下就可以了

代碼

	queue<int>q;
	for(int i=1;i<=n;i++)
	{
		if(rd[i]==0) q.push(i);
		//入度為0,入隊(duì) 
	}

核心部分

這部分的過程,我在前面是這樣說的:

用寬搜遍歷隊(duì)列。
那就寬搜。

寬搜

沒遍歷到一個(gè)點(diǎn),就將其彈出,并壓入拓?fù)鋽?shù)組。

對(duì)每個(gè)點(diǎn)的操作

我在前面這樣說:
對(duì)每個(gè)點(diǎn)的每輪遍歷步驟如下:
1.將這個(gè)點(diǎn)出隊(duì),并加入拓?fù)鋽?shù)組中
2.遍歷這個(gè)點(diǎn)的所有出度
3.將其出度點(diǎn)的入度數(shù)量減少一
4.如果其出度點(diǎn)入度為0,入隊(duì)

那就照著做嘛。
很簡單,實(shí)在看不懂代碼中有注釋。

代碼

	while(!q.empty())
	{
		int x=q.front();
		q.pop();
		topu.push_back(x);//推入拓?fù)鋽?shù)組 
		for(auto y:e[x])
		{
			rd[y]--;//刪掉一條邊 
			if(rd[y]==0)//入度為0 
			{
				q.push(y);//入隊(duì) 
			}
		}
	}

好,大功告成!

算法元代碼

上面沒看懂的話,看下面的代碼,含有注釋。

#include<bits/stdc++.h>
using namespace std;
const int NN=5005;
int n,m,rd[NN];
//rd[i]表示i點(diǎn)的入度數(shù) 
vector<int>e[NN],topu;
//e作為鄰接表存儲(chǔ)用,topu儲(chǔ)存拓?fù)湫?
void tuopu()
{
	queue<int>q;
	for(int i=1;i<=n;i++)
	{
		if(rd[i]==0) q.push(i);
		//入度為0,入隊(duì) 
	}
	while(!q.empty())
	{
		int x=q.front();
		q.pop();
		topu.push_back(x);//推入拓?fù)鋽?shù)組 
		for(auto y:e[x])
		{
			rd[y]--;//刪掉一條邊 
			if(rd[y]==0)//入度為0 
			{
				q.push(y);//入隊(duì) 
			}
		}
	}
}
int main()
{
	scanf("%d%d",&n,&m);
	for(int i=1;i<=m;i++)
	{
		int x,y;
		scanf("%d%d",&x,&y);
		rd[y]++;//x指向y,因此y入度數(shù)加1 
		e[x].push_back(y);//加邊 
	}
	tuopu();
	for(auto x:topu)
	{
		printf("%d ",x);//輸出拓?fù)湫?
	}
} 

總結(jié)

拓?fù)渑判蚓褪沁@回事:
首先,將入度為0的點(diǎn)入隊(duì)。
然后,用寬搜遍歷隊(duì)列。
在此之后,對(duì)每個(gè)點(diǎn)進(jìn)行如下操作:
1.將這個(gè)點(diǎn)出隊(duì),并加入拓?fù)鋽?shù)組中
2.遍歷這個(gè)點(diǎn)的所有出度
3.將其出度點(diǎn)的入度數(shù)量減少一
4.如果其出度點(diǎn)入度為0,入隊(duì)

下一篇文章,我將會(huì)詳細(xì)講解拓?fù)渑判蛳嚓P(guān)例題。
好,期待三連~~文章來源地址http://www.zghlxwxcb.cn/news/detail-723783.html

到了這里,關(guān)于拓?fù)渑判蛟斀猓ò惴ㄔ韴D解、算法實(shí)現(xiàn)過程詳解、算法例題變式全面講解等)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請(qǐng)注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請(qǐng)點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請(qǐng)作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包