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 }                                 

 

posted @ 2013-08-29 00:15  WarBean  阅读(408)  评论(0编辑  收藏  举报