Forest

来源:互联网 发布:ios的一个编程游戏 编辑:程序博客网 时间:2024/04/29 23:28

Forest

题目链接:http://soj.me/show_problem.php?pid=1001&cid=970

Description

In the field of computer science, forest is important and deeply researched , it is a model for many data structures . Now it’s your job here to calculate the depth and width of given forests.

     Precisely, a forest here is a directed graph with neither loop nor two edges pointing to the same node. Nodes with no edge pointing to are roots, we define that roots are at level 0 . If there’s an edge points from node A to node B , then node B is called a child of node A , and we define that B is at level (k+1) if and only if A is at level k .

      We define the depth of a forest is the maximum level number of all the nodes , the width of a forest is the maximum number of nodes at the same level.
Input
There’re several test cases. For each case, in the first line there are two integer numbers n and m (1≤n≤100, 0≤m≤100, m≤n*n) indicating the number of nodes and edges respectively , then m lines followed , for each line of these m lines there are two integer numbers a and b (1≤a,b≤n)indicating there’s an edge pointing from a to b. Nodes are represented by numbers between 1 and n .n=0 indicates end of input.
Output

For each case output one line of answer , if it’s not a forest , i.e. there’s at least one loop or two edges pointing to the same node, output “INVALID”(without quotation mark), otherwise output the depth and width of the forest, separated by a white space.


Sample Input
1 01 11 13 11 32 21 22 10 88
Sample Output
0 1INVALID1 2INVALID


题目描述:查找森林中树的最大深度depth,以及在同一层的最多结点数width。
输入:n,m (n个结点,m条边)
            a1,b1;
            a2,b2;
            .....(共m组,从结点a到b的边)
输出:深度和宽度,如果存在环路,输入:无效

分析:每次将0入度的结点(即根节点)入队,(0层宽度++)
           宽度优先搜索
           每个结点的深度 = 上一层 +1;
           宽度 = 所在层宽度+1;
           如存在入度>1的点,不符合树的特点,无效;
           所有搜索结束,若还有未visit的点,说明有环,如:1->2&&2->1,两个点都无法入队,无法修改visit信息。


代码:
#include <iostream>#include <string.h>using namespace std; const int MaxNum = 109;int n,m;int edge[MaxNum][MaxNum];      //此数组记录每个结点的边信息,如edge[a][n]=b意为结点a的第n条边是连接到b的int deg[MaxNum];                                        //此数组记录每个结点的出度int in[MaxNum];                                         //此数组记录每个结点的入度int dep[MaxNum];                                        //此数组记录某个结点的深度int number[MaxNum];                                     //此数组记录某一深度的宽度int open[MaxNum];                                       //此数组记录被访问的队列bool vst[MaxNum];                                       //此数组标记某结点是否被访问过int openN; void input(){     int i,a,b;     memset(deg,0,sizeof(deg));                           //初始化数组deg,in     memset(in,0,sizeof(in));     for(i = 0; i < m; i++)     {         cin>>a>>b;         edge[--a][deg[a]++] = --b;                      //a的第deg[a]条边连接到b         in[b]++;                                        //b的入度加     }}void solve(){     int i,j,x,v;     int depth = 0,width = 0;     openN = -1;     memset(vst,0,sizeof(vst));                          //初始化数组vst,number     memset(number,0,sizeof(number));          for(i = 0; i < n; i++)     {         if(in[i] == 0)                        //寻找入度为的结点作为广度优先搜索的开始结点         {              open[++openN] = i;              vst[i] = true;                              //将该结点标记为已访问              dep[i] = 0;                                 //根结点的深度为              number[0]++;                                //根结点的宽度加         }         else if(in[i] > 1)                              //若该结点的入度大于,不符合要求         {              cout<<"INVALID"<<endl;              return;         }     }     for(i = 0; i <= openN; i++)            //将找出来的根结点依次进行广度优先搜索,注意等号!      {         x = open[i];         for(j = 0; j<deg[x]; j++)                       //依次访问该结点的孩子         {              if(vst[v = edge[x][j]] == 1)                //若已经被访问过则说明有圈              {                   cout<<"INVALID"<<endl;                   return;              }              else              {                   vst[v] = true;                          //将此结点标记为已访问                   open[++openN] = v;                      //将此结点放入访问队列                   dep[v] = dep[x] + 1;                    //该结点的深度为其父结点深度加                   number[dep[v]]++;                       //该结点所在层宽度加              }         }     }     for(i = 0; i < n; i++)                               //依次查找是否有没有被访问过的结点     {         if(vst[i] == 0)                            //如果有结点没有被访问过则输出“INVALID”         {              cout<<"INVALID"<<endl;              return;         }         if(dep[i] > depth)                              //通过逐次替换找到答案              depth = dep[i];         if(number[i] > width)              width = number[i];     }     cout<<depth<<" "<<width<<endl;                      //输出结果}int main(){     cin>>n>>m;     while(n != 0)     {         input();         solve();         cin>>n>>m;     }    // system("pause");     return 0;}                                 


原创粉丝点击