1. 程式人生 > >圖的遍歷(深搜和廣搜的思想)

圖的遍歷(深搜和廣搜的思想)

一、深度優先搜尋遍歷圖

1、圖的儲存:二維陣列,i,j表示點,a[i][j]表示邊長。

//圖的dfs遍歷
#include<bits/stdc++.h>
using namespace std;

const int INF=0x3ffffff;
int n,m,sum;
int a[101][101],vis[101];

void dfs(int st)
{
	int i;
	printf("%d ",st);
	sum++;
	if(sum==n) return ; //訪問次數達到要求,結束。 
	
	for(i=1;i<=n;i++)
	{
		if(vis[i]==0&&a[st][i]==1) //訪問未訪問的節點 
		{
			vis[i]=1; //每次標記找過的節點 
			dfs(i); //遞迴查詢。 
		}
	}
	return ;
}

int main(void)
{
	int i,j;
	int v,u;
	memset(vis,0,sizeof(vis));
	scanf("%d %d",&n,&m);
	for(i=1;i<=n;i++) //初始化 
	{
		for(j=1;j<=n;j++)
		if(i==j) a[i][j]=0; 
		else a[i][j]=INF;
	}
	
	while(m--)
	{
		scanf("%d %d",&v,&u); //二維陣列儲存 
		a[v][u]=1;
		a[u][v]=1;
	}
	sum=1;
	vis[1]=1;
	dfs(1);
	return 0;
}

/*測試樣例 
5 5
1 2
1 3
1 5
2 4
3 5


結果輸出:
1 2 4 3 5 
*/ 

二、廣度優先搜尋的圖的遍歷

相當於二叉樹的層序遍歷,就是一一個點為中心,遍歷他周圍的節點。

//圖的bfs遍歷
#include<bits/stdc++.h>
using namespace std;

const int INF=0x3fffff;
int a[101][101],vis[101];  //二維陣列儲存結構和vis標記 
int q[101]; //相當於佇列,儲存資料。 

int main(void)
{
	int n,m,i,j;
	int u,v;
	memset(vis,0,sizeof(vis)); //初始化標記陣列 
	scanf("%d %d",&n,&m);
	for(i=1;i<=n;i++) //初始胡二維陣列 
	{
		for(j=1;j<=n;j++)
		if(i==j) a[i][j]=0;
		else a[i][j]=INF;
	}
	
	while(m--)
	{
		scanf("%d %d",&u,&v); //輸入無向圖 
		a[v][u]=1;
		a[u][v]=1;
	}
	//初始胡佇列 
	memset(q,0,sizeof(q));
	int head=1,tail=1,tp,sum=0;
	q[tail]=1;
	tail++;
	vis[1]=1;
	
	while(head<tail)
	{
		
		tp=q[head];
		for(i=1;i<=n;i++)  
		{
			if(vis[i]==0&&a[tp][i]==1)  //將未走過的節點進隊。 
			{
				vis[i]=1;
				q[tail]=i;
				tail++;
			}
			if(tail>n) //結束條件。 
			break;
		}
		head++;
	}
	
	for(i=1;i<tail;i++)  //遍歷輸出 
	printf("%d ",q[i]);
	return 0;
}

/*
輸入樣例:
5 5
1 2
1 3
1 5
2 4
3 5

輸出樣例:
1 2 3 5 4
*/ 

三、例題

計算出城市地圖的最短路徑。

//城市地圖(圖的深度優先遍歷) 
#include<bits/stdc++.h>
using namespace std;
int a[101][101],vis[101]; //二維陣列,標記陣列 
int mi,n,m; //最小值 
const int INF=0xffff;

void dfs(int tp,int dis)
{
	if(dis>mi) return ; //如果路徑大於原路徑就返回 
	if(tp==n)   //找到終點 
	{
		if(dis<mi) mi=dis;
		return ;
	}
	for(int i=1;i<=n;i++)
	{
		if(a[tp][i]!=INF&&vis[i]==0) //未標記過的路徑 
		{
			vis[i]=1;
			dfs(i,dis+a[tp][i]);
			vis[i]=0;
		}
	}
	return ;
}

int main(void)
{
	int i,j;
	scanf("%d %d",&n,&m);
	for(i=1;i<=n;i++) //二維陣列初始化 
	{
		for(j=1;j<=n;j++)
		if(i==j) a[i][j]=0;
		else a[i][j]=INF;
	}
	
	int u,v,w;
	while(m--)
	{
		scanf("%d %d %d",&u,&v,&w); 
		a[u][v]=w;
	}
	
	mi=INF;
	dfs(1,0);
	printf("%d\n",mi); //輸出最短路徑的結果。 
	return 0;
}

/*輸入樣例: 
5 8
1 2 2
1 5 10
2 3 3
2 5 7
3 1 4
3 4 4
4 5 5
5 3 3

輸出樣例:
9 
*/