poj 1300 欧拉回路、通路 解题报告
最近学了一些dp的皮毛之后,现在开始图论知识的学习,说实话,初步不知道怎么弄这个,然后无意间在网上下了一本关于图论的算法设计程序的教程,然后感觉还不错,结果后面才发现原来多年前,我的师兄就给了我这样一本好的资料。
感觉有点小悲催啊。。~ 有点对不起师兄的感觉,然后今天终于写了一个小知识点,欧拉回路的一题,其实这个也包含了通路的知识。
还是说一下题意吧。。
现在你是一个豪宅的管家,因为你有个粗心的主人,所以需要你来帮忙管理,输入会告诉你现在一共有多少个房间,然后会告诉你从哪个房间出发,你的任务就是从出发的房间通过各个房间之间的通道,来把所有的门都关上,然后最后回到0的房间。
一开始写的时候,我想因为我自己不是很熟悉图论的知识点,所以我就想用模拟的方法来做一做,结果让我碰对了,说实话 我不知道这样的深搜都可以过。。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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 }