首先,針對乙個這樣的題目開始我們的學習:輸入乙個有向圖,從頂點1開始做dfs對邊進行分類。
input
輸入的第一行包含兩個整數n和m,n是圖的頂點數,m是邊數。1<=n<=100,0<=m<=10000。
接下來的m行,每行是乙個數對u v,表示存在有向邊(u,v)。頂點編號從1開始。
接下來的1行,包含乙個整數k,表示會查詢k條邊的型別。
接下來的k行,每行是乙個數對u v,表示查詢邊u v的型別。
那麼:我們先來熟悉一下怎麼樣算是邊的分類,也就是有哪些邊的種類
1、樹邊 tree edge
2、向前邊 forward edge(本題目中為down edge)
3、向後邊 back edge
4、橫叉邊 cross edge
那麼我們怎麼利用這樣的分類區分不同的邊呢?
首先,我們根據深度優先搜尋的基本操作需要乙個記錄頂點相連的標誌,也就是edge[][]的乙個二維陣列,
然後,在遍歷各個頂點的過程中將遇到的可以訪問的edge設定為-1(初始化為0,輸入時置為1)也就是已經訪問過了,
至此,我們的樹就會生成,但是我們需要記錄其中不同邊的特性,所以,我們增加兩個標誌位pre,post來記錄開始和結束的時間點,
這個時間點起始點為0.
每當進行一次遍歷則會將對應的時間點記錄到相應頂點的pre和post中去,因此,我們可以有這樣的想法:
1、需要判斷一條邊為back edge的話,只需要檢視其相連頂點的post是否存在就可以了,因為從上到下的搜尋過程中,只有該頂點結束搜尋才會設定相應的結束時間
因而如果當前頂點的遍歷都沒有結束那麼說明與該點相連的頂點形成的邊是一條bakc edge。
2、從剛剛到back edge判斷中我們可以聯想發現,如果當前的頂點需要遍歷且相連頂點的pre(開始時間)比當前頂點的pre高,說明這條邊跳過一些時間點直接到此點
而且還是從較早到時間點跳轉到較晚的時間點,因此這樣的一條邊是一條down edge。
3、可想而知如果乙個頂點遍歷的開始時間點遠遠大於另外乙個頂點點話,這樣形成的一條邊自然就是cross edge了。
至此,應該就能夠基本解決這道問題了:
// problem#: 12120
// submission#: 3332350
// the source code is licensed under creative commons attribution-noncommercial-sharealike 3.0 unported license
// uri:
#include "iostream"
#include "cstring"
#include "algorithm"
#include "stdio.h"
using namespace std;
int pre[101],post[101],edge[101][101],parent[101];
int tag;
void dfs_tag(int cur,int n)else}}
}post[cur]=++tag;
}void dfs(int n)
}int main()
dfs(n);
cin>>cases;
while(cases--)}}
DFS深度優先搜尋中的標記問題
同樣是象棋中馬的問題,有以下兩個具體情景 問題1 給起點,走三步,求所有可能到達的點 問題2 給起點,不限制步數,求能否到達終點 上邊的dfs void dfs int x,int y,int s vis x y 0 下邊的dfs int dfs int x,int y vis x y 1 for ...
馬走日 深度優先搜尋
馬在中國象棋以日字形規則移動。請編寫一段程式,給定n m大小的棋盤,以及馬的初始位置 x,y 要求不能重複經過棋盤上的同乙個點,計算馬可以有多少途徑遍歷棋盤上的所有點。input 第一行為整數t t 10 表示測試資料組數。每一組測試資料報含一行,為四個整數,分別為棋盤的大小以及初始位置座標n,m,...
深度優先搜尋學習記錄
首先,深度優先搜尋與二叉樹遍歷中先序遍歷的原理十分相似,即一直向前走直到盡頭再返回 偽 描述 void dfs 一 8皇后問題 這道題有兩種做法 我知道的 是利用數字的全排列,求出每一位數字都不同的序列,此時滿足同一行同一列只有乙個皇后,只需判斷斜著有沒有皇后即可,可以利用 進行判斷 標準的dfs操...