soj 1034. Forest

方法来源:http://blog.csdn.net/guozhengchun/article/details/40761255


判断森林是否合法,以及找出最大宽度跟深度,上面博客的方法很好,是将森林变成树来处理的





#include <iostream>
#include <cstring>
#include <queue>

using namespace std;

struct node{
    int dad; //父节点 
    int child_num; //子节点数 
    int child[101]; //子节点编号 
    node(){
        dad=-1;  
        child_num=0;
        for(int i=0; i < 101; ++i) child[i]=-1;
    }
};

int main()
{
    int n,m;
    while(cin >> n >> m){
        node nn[101];
        if(n==0) break;
        if(m==0){
            cout << "0 " << n << endl;
            continue;
        }//没有边时 深度为0,但宽度为所有节点数 
        int a,b;
        for(int i=0; i < m; ++i){
            cin >> a >> b;
            nn[a].child[nn[a].child_num++] = b;//记录a的子节点为b 
            nn[b].dad=a;//b的父节点为a 
        }
        bool check=false;//合法的 
        int bian=m;//合成树后的新总边数 
        for(int i=1; i <= n; ++i){
            if(nn[i].dad==i){
                check=true;
                break;
            }//节点的父节点为本身,是环不合法,结束 
            if(nn[i].dad==-1){
                nn[i].dad=0;
                nn[0].child[nn[0].child_num++]=i;
                bian++;
            }//没有父节点的节点,作为节点0的子节点,然后新总边数+1 
        }
        if(n!=bian||check==true||m==bian){
            cout << "INVALID" << endl;
            continue;
        }/* n!=bian说明存在入度不为1的节点,因为新树的节点数为n+1
		正常的话节点=边数+1,即n+1=bian+1,如果不是就是说明有入度超过1
		
		check==true说明有节点的父节点为本身
		
		m==bian说明所有节点构成一个环 
        */ 
		queue<node> q;
        q.push(nn[0]);
        int maxwidth=-1;//记录最大的宽度,也就是我们要的结果 
        int pos=0;//当前结点在当前这一层的第几个位置,用于判断当前这层是否遍历完了 
        int nowwidth=1;//当点所在这层的宽度 
        int nextwidth=0;//下一层的宽度 
        int depth=-1;//深度,因为加了一个不存在的头节点,所以要从-1开始 
        int nodecount=0;//这棵树中总的节点数,用来判断是否存在环没有组成这颗树 
        node now;
        while(!q.empty()){
            now=q.front();
            q.pop();
            nodecount++;
            for(int i=0; i < now.child_num; ++i)
                    q.push(nn[now.child[i]]);//将下一层的节点入队 
            pos++;
            nextwidth+=now.child_num;//计算下一层的节点数,也就是宽度 
            if(pos==nowwidth){//如果当前位置到了这一层的最后一个节点 
                if(nextwidth > maxwidth)
                    maxwidth=nextwidth;//更新最大的宽度 
                nowwidth=nextwidth;//更新当前的宽度为下一层的宽度 
                nextwidth=0;//将下一层的宽度初始化为0 
                depth++;//深度加一 
                pos=0;// 初始化记录的位置 
            }
        }
        if(nodecount-1==n){
            cout << depth-1 << " " << maxwidth << endl;
        }
        else cout << "INVALID" << endl;//存在环没构成树 

    }
} 


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值