活动地址:CSDN21天学习挑战赛
学习的最大理由是想摆脱平庸,早一天就多一份人生的精彩;迟一天就多一天平庸的困扰。
给定一个有N个顶点和E条边的无向图,请用DFS和BFS分别列出其所有的连通集。假设顶点从0到N−1编号。进行搜索时,假设我们总是从编号最小的顶点出发,按编号递增的顺序访问邻接点。
输入第1行给出2个整数N(0
按照"{ v1 v2…vk}"的格式,每行输出一个连通集。先输出DFS的结果,再输出BFS的结果。
8 6
0 7
0 1
2 0
4 1
2 4
3 5
{ 0 1 4 2 7 }
{ 3 5 }
{ 6 }
{ 0 1 2 7 4 }
{ 3 5 }
{ 6 }
#include
#include
//深搜
void dfs(int map[][15],int f[],int n,int x){
printf("%d ",x);
for(int i=0;i<n;i++){
map[i][x]=0;
}
for(int i=0;i<n;i++){
if(map[x][i]&&!f[i]){
map[x][i]=0;
map[i][x]=0;
f[i]=1;
dfs(map,f,n,i);
}
}
}
//广搜
void bfs(int map[][15],int f[],int n,int x){
for(int i=0;i<n;i++){
map[i][x]=0;
}
for(int i=0;i<n;i++){
if(map[x][i]&&!f[i]){
printf("%d ",i);
f[i]=1;
}
}
for(int i=0;i<n;i++){
if(map[x][i]){
map[x][i]=0;
map[i][x]=0;
bfs(map,f,n,i);
}
}
}
void init(int map[][15],int temp[][15],int n){
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
temp[i][j]=map[i][j];
}
}
}
int main()
{
int n,e;
int v,u;
int map[15][15],temp[15][15];
int flag[15];
while(scanf("%d%d",&n,&e)!=EOF)
{
memset(map,0,sizeof(map));
for(int i=1;i<=e;i++){
scanf("%d%d",&v,&u);
map[v][u]=1;
map[u][v]=1;
}
memset(flag,0,sizeof(flag));
init(map,temp,n);
for(int i=0;i<n;i++){
if(!flag[i]){
flag[i]=1;
printf("{ ");
dfs(temp,flag,n,i);
printf("}\n");
}
}
init(map,temp,n);
memset(flag,0,sizeof(flag));
for(int i=0;i<n;i++){
if(!flag[i]){
flag[i]=1;
printf("{ %d ",i);
bfs(temp,flag,n,i);
printf("}\n");
}
}
}
}
就是深搜广搜,emmm,我也就照着我自己的思路写的,如果有更简单的更简洁的代码可以一起分享一下。
深搜就是路经该结点的路劲有多条,先走完一条路径再回来走另一条。广搜就是一个结点下有多个结点可以走,那就先走完输出所有结点,然后再走这些节点的下一个结点,就相当于二叉树的层次遍历,上层结点走完再走下层节点。

样例我们可以得出上图这样一张图,我是用邻接表存的,反正画出来就是这么一个无向图。
深搜DFS的步骤的如下:
从0开始,我们题目要求从编号小的开始,集合{0}。

然后呢这时,0有两个连接的结点,1和2,从小的开始那就是先走1.集合{0,1}

这时候1有结点4连接,深度优先嘛,先走到底,那么接下来走4.得到集合{0,1,4}

然后4后还有一个相邻结点2,那么走2,得到集合{0,1,4,2}

此时这条路径已经走不下去了,没有可以走的地方了,然后就网上退,0这里还有路可以走7,得到集合{0,1,4,2,7}

这时候这一条路径完全走完了,走不了了,那就走下一个结点小的没走过的路径,那就是3开始,接下来就不赘述了。
广搜步骤介绍
依旧是从结点编号小的开始,得到集合{0}

广搜啊,所以要找当前节点相邻的所有结点,走完这些结点才可以继续。那么接下来就找相邻结点,那就是1,2,7,分别走过。小的优先,得到集合{0,1,2,7}

然后从刚才走过的结点开始往下找相邻的结点,把他们下一层结点都遍历了。遍历结点1的下一层,得到集合{0,1,2,7,4}

此时这条路径已经没有结点可以遍历了,接着便利其他未走过的路径,就不赘述了。
我理解的就是这样的,如果有问题可以及时指出,共同探讨。
我不理解但是,为什么说我的文章质量差来着。

一般来说,广搜常用于找单一的最短路线,或者是规模小的路径搜索,它的特点是"搜到就是最优解", 而深搜用于找多个解或者是"步数已知(好比3步就必需达到前提)"的标题,它的空间效率高,然则找到的不必定是最优解,必需记实并完成全数搜索,故一般情况下,深搜需要很是高效的剪枝(优化).
像搜索最短路径这些的很显著若是用广搜,因为广搜的特征就是一层一层往下搜的,保证当前搜到的都是最优解,当然,最短路径只是一方面的操作,像什么起码状态转换也是可以操作的。
深搜就是优先搜索一棵子树,然后是另一棵,它和广搜对比,有着内存需要相对较少的所长,八皇后标题就是典范楷模的操作,这类标题很显著是不能用广搜往解决的。或者像图论里面的找圈的算法,数的前序中序后序遍历等,都是深搜
深搜和广搜的分歧之处是在于搜索次序的分歧。
深搜的实现近似于栈,每次选择栈顶元素往扩年夜,
广搜则是操作了队列,先被扩年夜的的节点优先拿往扩年夜。
搜索树的形态:深搜层数良多,广搜则是很宽。
深搜合适找出所有方案,广搜则用来找出最佳方案
深搜和广搜的分歧:
深搜并不能保证第一次碰着方针点就是最短路径,是以要搜索所有可能的路径,是以要回溯,标识表记标帜做了之后还要打消失踪,是以统一个点可能被访谒良多良多次。而广搜因为它的由近及远的结点扩年夜次序,结点老是以最短路径被访谒。一个结点假如第二次被访谒,第二次的路径确定不会比第一次的短,是以就没有需要再从这个结点向周围扩年夜――第一次访谒这个结点的时辰已经扩年夜过了,第二次再扩年夜只会获得更差的解。是以做过的标识表记标帜不必往失踪。是以统一个点至多只可能被访谒一次。每访谒一个结点,与它相连的边就被搜检一次。是以最坏情况下,所有边都被搜检一次,是以时刻复杂度为O(E)。