Sicily 1034 Forest——判断图中是否有环路
这道题要求在一个图里面确定是否存在环路,如果没有,则输出该森林的高度和宽度,其中高度定义为叶子离根最远的距离,宽度定义为同一高度中节点数的最大值。
一开始的思路是找到所有入度为0的源点,然后深搜之,如果遇到已访问的点就说明存在环路。但是没有考虑到有些环路中不存在入度为0的点,比如1->2, 2->3, 3->1这种。所以还是在深搜退出后判断是否还有未访问的点。先前还想过用“不存在源点”来代替“存在无源点的环路”的检测,但是可能同时存在有源点的环路和无源点的环路,所以此路不通。代码如下:
1 // Problem#: 1034 2 // Submission#: 2194590 3 // The source code is licensed under Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License 4 // URI: http://creativecommons.org/licenses/by-nc-sa/3.0/ 5 // All Copyright reserved by Informatic Lab of Sun Yat-sen University 6 #include<iostream> 7 #include<cstring> 8 #include<vector> 9 10 using namespace std; 11 12 int n,m; 13 vector<int> edge[101]; 14 bool visit[101]; 15 bool ok; 16 int level[101]; 17 18 //对某个入度为0的点进行深搜 19 void dfs(int u, int lv) 20 { 21 //遇到访问过的点说明有环 22 if(visit[u]) 23 { 24 ok = false; 25 /*cout<<"break at "<<u<<endl; 26 cout<<"hello"<<endl;*/ 27 return ; 28 } 29 visit[u] = true; 30 //深度为lv的点数增加1 31 level[lv] ++; 32 //对于当前点u可以达到的所有点进行深搜 33 bool flag = true; 34 for(int i = 0; i < edge[u].size(); i ++) 35 { 36 dfs(edge[u][i], lv + 1); 37 if(!ok) 38 return ; 39 } 40 } 41 42 int main() 43 { 44 int i; 45 int u,v; 46 bool flag; 47 int width; 48 int in[101]; //各点入度 49 while((cin>>n>>m) && n) 50 { 51 ok = true; 52 memset(in, 0, sizeof(in)); 53 memset(edge, 0, sizeof(edge)); 54 memset(level, 0, sizeof(level)); 55 memset(visit, false, sizeof(visit)); 56 //读入有向边 57 for(i = 1; i <= m; i ++) 58 { 59 cin>>u>>v; 60 edge[u].push_back(v); 61 in[v] ++; 62 } 63 for(i = 1; i <= n; i ++) 64 { 65 //检测是否入度为0,若是,深搜之 66 if(in[i] == 0) 67 { 68 dfs(i, 0); 69 if(!ok) 70 break; 71 } 72 } 73 //提前跳出或者找不到入度为0的源点,说明检测到有环 74 if(!ok) 75 { 76 cout<<"INVALID"<<endl; 77 continue; 78 } 79 //有未被访问的点说明存在环,而环上的点入度均不为零 80 for(int i = 1; i <= n; i ++) 81 if(!visit[i]) 82 { 83 ok = false; 84 break; 85 } 86 if(!ok) 87 { 88 cout<<"INVALID"<<endl; 89 continue; 90 } 91 width = 0; 92 for(i = 0; level[i] != 0; i ++) 93 if(width < level[i]) 94 width = level[i]; 95 cout<<i - 1<<' '<<width<<endl; 96 97 /*for(int i = 1; i <= n; i ++) 98 { 99 for(int j = 0; j < edge[i].size(); j ++) 100 cout<<edge[i][j]<<' '; 101 cout<<endl; 102 }*/ 103 } 104 return 0; 105 }