题目链接:http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=ALDS1_11_B
邻接表的方式给一个图,输出对这个图进行dfs之后,每个节点的开始搜索和结束搜索时间。
首先,如果我想做对一个邻接矩阵的深度优先遍历,dfs
我需要用一个栈来存储,我需要访问的元素。
首先把第一个节点放进去,然后按照顺序遍历一遍节点表,如果有边能通向一个还没有访问过的节点,那么就把这个节点放进去;直到,最后放进去的这个节点,它所有的边通向的节点,都访问过了,那么就开始pop出来一个元素,然后搜索最顶端的元素,是不是还有其他相邻节点没有被访问过,如果有,就push进栈里。。重复这个操作,知道都访问过。
但是由于,在转换为邻接矩阵的时候,只保留了一半路径,可能会出现,有的节点访问不到的情况,所以加上修正。这种情况的测试数据如下:
6
1 2 2 4
2 1 5
3 2 5 6
4 0
5 1 4
6 1 6
-----output-----
1 1 8
2 2 7
3 0 0
4 4 5
5 3 6
6 0 0
整体代码如下:
#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#include <queue>
#include <stack>
#include <cstring>
using namespace std;
bool A[110][110],flag[110];
int in[110],out[110];
int n,now=1;
stack<int> S;
void dfs_visit(int u){
flag[u]=true;
for(int i=1;i<=n;i++){
if(A[u][i]==true && flag[i]==false) {
S.push(i);
in[i]=now++;
dfs_visit(i);
}
}
int x=S.top();
S.pop();
out[x]=now++;
return ;
}
void dfs(){
S.push(1);in[1]=now++;
L1: while(S.empty()==0){
int x=S.top();
dfs_visit(x);
}
for(int i=1;i<=n;i++){
if(flag[i]==false){
S.push(i);in[i]=now++;goto L1;
}
}
for(int i=1;i<=n;i++) cout<<i<<" "<<in[i]<<" "<<out[i]<<endl;
return ;
}
int main (){
int a,b,c;
cin>>n;
for(int i=1;i<=n;i++){
flag[i]=false;
for(int j=1;j<=n;j++){
A[i][j]=false;
}
}
for(int i=1;i<=n;i++){
cin>>a>>b;
for(int j=1;j<=b;j++){
cin>>c;
A[a][c]=true;
}
}
dfs();
return 0;
}
错点:
1.考虑到存储的问题,加上修正。
for(int i=1;i<=n;i++){
if(flag[i]==false){
S.push(i);in[i]=now++;goto L1;
}
}
2.注意初始化
3.注意第一次push(1)进去的时候,要对1的intime自己写。
也可以用递归的方式完成,代码如下:
#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
bool A[110][110];
int flag[110],in[110],out[110];
int now=1,n;
void dfs(int u){
flag[u]=1;
in[u]=now++;
for(int i=1;i<=n;i++){
if(flag[i]==0 && A[u][i]==true){
dfs(i);
}
}
out[u]=now++;
return ;
}
int main(){
int a,b,c;
cin>>n;
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
A[i][j]=false;
}
}
for(int i=1;i<=n;i++){
cin>>a>>b;
for(int j=1;j<=b;j++){
cin>>c;
A[a][c]=true;
}
}
for(int i=1;i<=n;i++){
if(flag[i]==0) dfs(i);
}
for(int i=1;i<=n;i++){
cout<<i<<" "<<in[i]<<" "<<out[i]<<endl;
}
return 0;
}
错点:
1.注意in和out time赋值的时间。
----------------8th June update------------------
直接用栈来实现dfs的实现中,可以把“先把1节点push进栈”这个操作放到后面的修正步骤中,来避免使用goto。
同时,dfs函数可以直接放到main函数里面,直接用dfs_visit来递归调用dfs
整体代码如下:
#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#include <queue>
#include <stack>
#include <cstring>
using namespace std;
bool A[110][110],flag[110];
int in[110],out[110];
int n,now=1;
stack<int> S;
void dfs_visit(int u){
flag[u]=true;
for(int i=1;i<=n;i++){
if(A[u][i]==true && flag[i]==false) {
S.push(i);
in[i]=now++;
dfs_visit(i);
}
}
int x=S.top();
S.pop();
out[x]=now++;
return ;
}
int main (){
int a,b,c;
cin>>n;
for(int i=1;i<=n;i++){
flag[i]=false;
for(int j=1;j<=n;j++){
A[i][j]=false;
}
}
for(int i=1;i<=n;i++){
cin>>a>>b;
for(int j=1;j<=b;j++){
cin>>c;
A[a][c]=true;
}
}
for(int i=1;i<=n;i++){
if(flag[i]==false){
S.push(i);in[i]=now++;
while(S.empty()==0){
int x=S.top();
dfs_visit(x);
}
}
}
for(int i=1;i<=n;i++) cout<<i<<" "<<in[i]<<" "<<out[i]<<endl;
return 0;
}