1034.Forest(判断是否为森林,存在入度超过1或有回路的不成森林)

该博客探讨了如何判断一个图是否为森林,重点在于实现一个判断森林的算法,包括计算传递闭包、检查是否存在入度超过1的节点以及回路。通过DFS遍历和矩阵操作来检测图的性质,最终确定森林的深度和宽度。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

/*1034.Forest(求传递闭包判断回路,判断是否为森林,存在入度超过1或有回路的不成森林)
*/
#include <iostream>
#include <stdlib.h>
#include <memory.h>
#include <vector>
using namespace std;

struct Node
{
    vector<int> adj;
}node[101];     
  

int n, m;
int inDegree[101];
int matrix[101][101];
int width[101];
int treeLevel;
int forestLevel;

inline void DFS(int k, int level)
{
    //统计每一层的节点数 
    width[level]++;
    //判断树的深度是否比森林深度大,若是更新森林深度 
    if(treeLevel < level)
          treeLevel = level;
    for(int i=0; i< node[k].adj.size(); i++)
    {
        DFS(node[k].adj[i], level+1);
    }
}

inline bool isForest()
{
    for(int i=1; i<=n; i++)
       if(inDegree[i] > 1)
          return false;            
    //求出图的传递闭包
    // 例如 i->k,i可以到达k,则就在i列中,找出可以到达i的j,扫描k列所有行即可 
    for(int i=1; i<=n; i++)
      for(int k=1; k<=n; k++)
          if(matrix[i][k])
          {
             //扫描k列所有的行 
             for(int j=1; j<=n; j++)
               if(matrix[j][i])  //如果存在j可达i,则说明j也可到k 则令其为1
                 matrix[j][k] =1;             
          }        
          
    //找完闭包后,要判断是否形成回路闭包,只需要判断是否存在节点i可以连通到自身
    for(int i=1; i<=n ; i++)
       if(matrix[i][i])
         return false; 
    return true;
}

int main()
{
    int start, end;
    while(cin >> n >> m && n !=0)
    {
        memset(inDegree,0, sizeof(inDegree));
        memset(matrix,0, sizeof(matrix));
        memset(width,0, sizeof(width));
        memset(node, 0, sizeof(node));  //注意要初始化node数组 
        for(int i=1; i<=m; i++)
        {
            cin >> start >> end;
            matrix[start][end] = 1;
            inDegree[end]++;
            node[start].adj.push_back(end);
        }
        forestLevel =0;
        if(!isForest())   //判断是否存在回路闭包或者是否存在入度超过1的点 
           cout << "INVALID" << endl;
        else 
        {
           for(int i=1; i<=n; i++)
           {
               //对森林每棵树进行DFS,统计出各颗树的深度和广度 
               if(inDegree[i] == 0)
               {
                  treeLevel = 0;
                  DFS(i, 0); 
                  if(treeLevel > forestLevel)   
                    forestLevel = treeLevel;     
               }  
           } 
           int maxWidth = 0;
           for(int i=0; i< 101; i++)
             if(maxWidth < width[i])
               maxWidth = width[i];
           cout << forestLevel << " "<< maxWidth << endl;
        }             
    }
    system("pause");
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值