图的遍历
图的遍历主要是由深搜和广搜来完成的,基本上没什么难点。
例1.第一行输入两个数字n和m,n表示n个数,m表示n个数之间有m条连线;接下来m行每行有两个数,代表这两个数之间的连线,遍历这张图,每个数出现一次。
例2.第一行输入两个数字n和m,n表示n个数,m表示n个数之间有m条单向连线;接下来m行每行有三个数,第三个数代表前两个数之间的连线长度,输出由1到n的最短步数。
话不多说,上代码(若有错误地方,还请大佬执指正):
例1.
//深搜
#include<stdio.h>
int n,blk[101],e[101][101],sum; //blk数组用来判断是否已经遍历当前数字,e数组用来存储两个数之间的连线
void dfs(int cur)
{
int i;
printf("%d ",cur); //输出当前数字
sum++;
if(sum==n) //每输出一个sum+1,当输出n个数返回
return ;
for(i=1;i<=n;i++)
{ //判断当前数与未遍历的数有无连线
if(e[cur][i]==1 && blk[i]==0)
{
blk[i]=1; //记录下这个数并进行下一次查找
dfs(i);
}
}
}
int main()
{
int m,i,j,a,b;
scanf("%d %d",&n,&m);
for(i=1;i<=n;i++) //初始化数组,每个数到他自己记为0,其他记为正无穷(99999)
for(j=1;j<=n;j++)
if(i==1)
e[i][j]=0;
else
e[i][j]=99999;
for(i=1;i<=m;i++)
{
scanf("%d %d",&a,&b); //读入连线
e[a][b]=1;
}
blk[1]=1; //记录第一个数
dfs(1); //从第一个数开始遍历
return 0;
}
//广搜,与上面代码意思相近,可以自己理解
#include<staio.h>
int main()
{
int e[101][101],blk[101],n,m;
int i,j,a,b;
scanf("%d %d",&n,&m);
for(i=1;i<=n;i++)
for(j=1;j<=n;j++)
if(i==j)
e[i][j]=0;
else
e[i][j]=999909;
for(i=0;i<m;i++)
{
scanf("%d %d",&a,&b);
e[a][b]=1;
}
int que[101],head,tail;
head=1;tail=1;
que[tail]=1;
tail++;
while(head<tail)
{
int cur=que[head];
for(i=1;i<=n;i++)
{
if(e[cur][i]==1 && blk[i]==0)
{
blk[i]=1;
que[tail]=i;
tail++;
}
}
if(tail>n)
break;
head++;
}
for(i=1;i<=n;i++)
printf("%d ",que[i]);
return 0;
}
例2.
//深搜,广搜可以自己尝试
#include<stdio.h>
int n,e[101][101],ans,blk[101],min=999999; //与上题接近,这里min用来存储答案
void dfs(int cur,int ans)
{
int i,j;
if(ans>min) //如果当前答案大于最小值,则没必要继续遍历,直接返回
return ;
if(cur==n) //如果走到目标位置,更新最小值,返回
{
if(ans<min)
min=ans;
return ;
}
for(i=1;i<=n;i++) //遍历
{
if(e[cur][i]!=99999 && blk[i]==0) //如果当前位置到i有连线,并且i点未走过,记录i点并更新ans
{
blk[i]=1; //标记i点
dfs(i,ans+e[cur][i]); //继续遍历
blk[i]=0; //取消标记,深搜,很好理解
}
}
}
//主函数用来读入地图
int main()
{
int i,j,m,a,b;
scanf("%d %d",&n,&m);
for(i=1;i<=n;i++)
for(j=1;j<=n;j++)
if(i==j)
e[i][j]=0;
else
e[i][j]=99999;
for(i=0;i<m;i++)
{
scanf("%d %d %d",&a,&b,&j);
e[a][b]=j;
e[b][a]=j;
}
blk[1]=1; //标记第一个点
dfs(1,0);
printf("%d",min);
}
以上