poj 1300 欧拉回路、通路 解题报告

最近学了一些dp的皮毛之后,现在开始图论知识的学习,说实话,初步不知道怎么弄这个,然后无意间在网上下了一本关于图论的算法设计程序的教程,然后感觉还不错,结果后面才发现原来多年前,我的师兄就给了我这样一本好的资料。

感觉有点小悲催啊。。~   有点对不起师兄的感觉,然后今天终于写了一个小知识点,欧拉回路的一题,其实这个也包含了通路的知识。

还是说一下题意吧。。 

现在你是一个豪宅的管家,因为你有个粗心的主人,所以需要你来帮忙管理,输入会告诉你现在一共有多少个房间,然后会告诉你从哪个房间出发,你的任务就是从出发的房间通过各个房间之间的通道,来把所有的门都关上,然后最后回到0的房间。

一开始写的时候,我想因为我自己不是很熟悉图论的知识点,所以我就想用模拟的方法来做一做,结果让我碰对了,说实话  我不知道这样的深搜都可以过。。

View Code
  1   #include<iostream>
  2   #include<stdio.h>
  3   using namespace std;
  4   int graph[22][22]; 
  5   int n,Count,edgetotal,flag;
  6   void dfs(int i)
  7   {
  8        if(flag)return ;
  9        if(i==0&&Count==edgetotal){flag=1;return ;}//当你回到0房间的时候已经关闭了所有的门,那么就可以完成
 10        for(int j=0;j<n;j++)
 11        {
 12           if(graph[i][j]>0)
 13           {
 14               graph[i][j]--;
 15               graph[j][i]--;
 16               Count++;
 17               dfs(j);
 18               if(flag)return ;
 19               graph[i][j]++;
 20               graph[j][i]++;
 21               Count--;
 22           }     
 23        }
 24   }
 25   int main()
 26   {
 27      char temp[100];
 28      int start,end;
 29      while(gets(temp))
 30      {
 31         if(!strcmp(temp,"ENDOFINPUT"))break;
 32         flag=Count=edgetotal=0;
 33         int len=strlen(temp),sub=6;
 34         n=start=0;
 35         while(temp[sub]!=' '){start=start*10+(temp[sub]-48);sub++;}sub++;
 36         while(sub<len){n=n*10+(temp[sub]-48);sub++;}
 37         memset(graph,0,sizeof(graph));
 38         for(int i=0;i<n;i++)
 39         {
 40              gets(temp);
 41              len=strlen(temp);
 42              for(int j=0;j<len;j++)
 43              {
 44                 end=0;
 45                 while(temp[j]!=' '&&j<len){end=end*10+(temp[j]-48);j++;}
 46                 graph[i][end]++;
 47                 graph[end][i]++;
 48                 edgetotal++;
 49              }
 50         }
 51         gets(temp);
 52         dfs(start);
 53         if(flag)printf("YES %d\n",edgetotal);
 54         else
 55         printf("NO\n");
 56      }
 57      return 0;    
 58   }
 59   其实实际上,最好的解题方法还是来自图论当中的知识,相信有一点图论知识的人都知道,现在给你n个节点,那么这些节点当中如果每个节点的度都是偶数的话,那么一定可以从一个点出发然后回到这个点,并且访问整个路径当中的边。
 60   如果是要测试出通路的话,那么就是检查是否存在两个度为基数的节点,两个节点分别为起点和终点。
 61   #include<iostream>
 62   #include<stdio.h>
 63   using namespace std;
 64   int main()
 65   {
 66       char temp[100];
 67       int door_start,room,door[25],door_total;
 68       int door_num;//度数为基数的节点个数 
 69       while(scanf("%s",temp))
 70       {
 71              if(!strcmp(temp,"ENDOFINPUT"))break;
 72              scanf("%d%d",&door_start,&room);
 73              getchar();
 74              memset(door,0,sizeof(door));
 75              door_total=0;
 76              for(int i=0;i<room;i++)
 77              {
 78                 gets(temp);
 79                 int len=strlen(temp);
 80                 for(int j=0;j<len;j++)
 81                 {
 82                    int end=0;
 83                    while(temp[j]!=' '&&j<len){end=end*10+temp[j]-48;j++;}
 84                    door[i]++;
 85                    door[end]++;
 86                    door_total++;
 87                 }
 88              }
 89              gets(temp);
 90              door_num=0;
 91              for(int i=0;i<room;i++)
 92              {
 93                  if(door[i]%2)door_num++;
 94              }      
 95              if(door_num==0&&door_start==0)printf("YES %d\n",door_total);
 96   //如果不存在基数度的节点,那么当起点是0的时候,一定可以完成回路,访问所有的边。           
 97   else
 98              if(door_num==2&&door[0]%2==1&&door[door_start]%2==1&&door_start!=0)printf("YES %d\n",door_total);//如果基数点为2的话,那么当两个基数点为起点和终点的时候,此时只要终点与起点不重合,那么就可以完成通路,访问所有的边。
 99              else
100              printf("NO\n");
101       }
102      return 0;                             
103   }

 

posted @ 2012-09-01 21:45  诺小J  阅读(216)  评论(0编辑  收藏  举报