dfs 算法的使用

dfs 算法的使用

  • 算法思想,dfs算法是一个递归的过程,有回退的过程,对于一个无向连通图,访问图中某个顶点v0后,然后访问它的某一个邻接顶点v1,然后再从v1出发,访问v1的违访问过的邻接顶点,如此下去,直至到达所有的领接顶点都被访问过。然后回退一步,回到前一次被访问的顶点,看是否还有没有访问的顶点,如果有,则从这个顶点出发,进行向上述的过程一样进行访问,如果没有,则再回退一步,进行类似的访问,直至所有的顶点都被访问为止!
  • dfs算法用伪码来实现。

       1.如果图是用邻接表存储

      dfs(顶点i)

    {

        visited[i]=1;

        p是i的边链表表头指针

         while(p非空)

        {

               if(i顶点对应的另一个顶点没有被访问过,设为k)

             {

                 递归搜索前要准备的工作的代码在这些

                     dfs(k);

                    回退过程中,应该在这里写代码

             }

         p=p->next;

      }

   2 如果图是用邻接矩阵存储

   dfs(顶点i)

   {

        visited[i]=1;

        for(j=0;j<n;j++)

        {    if(edge[i][j]<inf&&visited[j]!=1) //如果i到k之间有边链接,并且j没有被访问过

              {  dfs(j);

              }

       }

}

  • 应用:来自南阳理工学院oj平台(非常适合初学者在上面刷题)附上链接http://acm.nyist.net/JudgeOnline/problemset.php  题目是第42题,一笔画问题,该题主要是用 欧拉通路问题,用到了dfs搜索!

         

复制代码
  1   #include<cstdio>
  2 #define maxn 1001
  3 #include<memory.h>
  4 struct anode
  5 {
  6     int to;
  7    // int adj;
  8     struct anode* next;
  9 };
 10 anode* list[maxn];
 11 int visited[maxn];
 12 int n,m;
 13 void dfs(int start)
 14 {
 15        anode *p;
 16         p=list[start];
 17         visited[start]=1;
 18         while(p)
 19         {
 20             if(!visited[p->to])
 21             {

 22                 dfs(p->to);
 23             }
 24             p=p->next;
 25         }
 26 
 27 }
 28 int  fun2()
 29 {
 30     int i;
 31     for(i=1;i<=n;i++)
 32     {
 33         if(visited[i]==0)
 34         return 0;
 35         break;
 36     }
 37     return 1;
 38 }
 39 void fun()
 40 {
 41     int jdnum=0;
 42     //int start1,start2;
 43     anode *p;
 44     int i;
 45     for(i=1;i<=n;i++)
 46     {
 47         int dnum=0;
 48         p=list[i];
 49         while(p)
 50         {
 51             dnum++;
 52             p=p->next;
 53         }
 54         if(dnum%2!=0)
 55         {
 56             jdnum++;
 57         }
 58     }
 59     if(fun2()==0)
 60     printf("No\n");
 61     else
 62     {
 63         if(jdnum!=0&&jdnum!=2)
 64        {
 65        printf("No\n");
 66        }
 67        else
 68        printf("Yes\n");
 69     }
 70 
 71 }
 72 
 73 int main()
 74 {
 75     int kase;
 76    // freopen("a.txt","r",stdin);
 77     scanf("%d",&kase);
 78     while(kase--)
 79     {
 80         scanf("%d%d",&n,&m);
 81         anode *p1,*p2;
 82         int v1,v2,i;
 83         memset(visited,0,sizeof(visited));
 84         memset(list,0,sizeof(list));
 85         for(i=0;i<m;i++)
 86         {
 87             scanf("%d%d",&v1,&v2);
 88             p1=new anode;
 89             p2=new anode;
 90             p1->to=v2;
 91             p1->next=list[v1];
 92             list[v1]=p1;
 93             p2->to=v1;
 94              p2->next=list[v2];
 95             list[v2]=p2;
 96         }
 97         dfs(v1);
 98         //fun2();
 99         fun();
100     }
101     return 0;
102 
103 }
104        
复制代码

其中dfs()函数是用来判断这个图是否连通,该题的图是用到邻接表来存储的,这样就不至于超时!

另外在附上一题用dfs来做同样来自南阳理工学院第27题

复制代码
 1  
 2 #include<stdio.h>
 3 int grid[101][101];
 4 int m,n;
 5 int dir[4][2]={{-1,0},{1,0},{0,1},{0,-1}};
 6 void dfs(int x,int y)
 7 {
 8     int i,xx,yy;
 9     grid[x][y]=0;
10     for(i=0;i<4;i++)
11     {
12         xx=x+dir[i][0];
13         yy=y+dir[i][1];
14         if(xx<0||yy<0||x>m||y>=n)
15         continue;
16         if(grid[xx][yy]==1)
17         dfs(xx,yy);
18     }
19 }
20 int main()
21 {
22     int i,j;
23     int h,count;
24     scanf("%d",&h);
25     while(h--)
26     {
27         scanf("%d%d",&m,&n);
28         for(i=0;i<m;i++)
29         {
30             for(j=0;j<n;j++)
31             scanf("%d",&grid[i][j]);
32         }
33          count=0;
34         for(i=0;i<m;i++)
35         {
36             for(j=0;j<n;j++)
37             {
38                 if(grid[i][j]==1)
39                 {
40                     dfs(i,j);
41                     count++;
42                 }
43             }
44 
45         }
46         printf("%d\n",count);
47     }
48     return 0;
49 }
50         
复制代码

这题纯粹是用dfs来解题,能够很好的体现dfs的思想!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值