森林
//sicily 1034. Forest
// 1.如果有任一节点的入度>1 或者没有根节点,则不是森林,否则:
// 2.先找根节点(入度为0的节点),压入栈.
// 3.对栈中的根结点(当前)删除掉,把所有子节点压入栈,重复这过程.最后若所有结点都曾压入栈中,则能构成森林,反之则说明有环存在
#include<iostream> //BFS求森林深度和宽度
#include<stdio.h>
#include<vector>
#include<stack>
#include<cstring>
using namespace std;
struct Node
{
int inDgr; //入度数
vector<int >next; //表示它的孩子结点
int height;
};
int width[200]; //高度i上的宽度width[i]
int max_height,max_width;
int main()
{
int n,m,i;
while(scanf("%d%d",&n,&m)&&n)
{
Node node[200];
for(i=1;i<=n;++i) //每次把所有结点的入度数初始化为0
node[i].inDgr=0;
bool isforest=true;
int f,c;
while(m--)
{
scanf("%d%d",&f,&c);
node[f].next.push_back(c);
node[c].inDgr++;
if(node[c].inDgr>1) //说明有两条边指向同个结点
isforest=false;
}
if(!isforest)
{
printf("INVALID\n"); continue;
}
memset(width,0,sizeof(width));
stack<int> root_stack; //栈中元素是入度为0的节点
for(i=1;i<=n;i++)
if(node[i].inDgr==0)
{
root_stack.push(i); //入度为0的节点压入栈
node[i].height=0;
width[0]++; //一开始所有的根结点都在第0层
}
if(root_stack.empty()) //没有根结点,那么肯定是有环
{
printf("INVALID\n"); continue;
}
int roots=0;
max_height=max_width=0;
while(!root_stack.empty())
{
roots++;
int top=root_stack.top();
root_stack.pop();
if(max_height<node[top].height)
max_height=node[top].height;
for(vector<int >::iterator ite=node[top].next.begin();ite!=node[top].next.end();++ite)
{
node[*ite].height=node[top].height+1; //儿子节点的深度=父节点+1
width[node[*ite].height]++; //在这一高度上的宽度数增加1
root_stack.push(*ite);
}
}
if(roots<n) //环内任意结点的入度都至少为1,都不会被压入栈,所以小于n则说明存在环
{
printf("INVALID\n"); continue;
}
for (i=0;i<n;i++)
if(width[i]>max_width)
max_width=width[i];
printf("%d %d\n",max_height,max_width);
}
return 0;
}