题目1448:Legal or Not

16 篇文章 0 订阅
// 用拓扑排序判断是否是有向无环图。。。 
#include<stdio.h>
#include<vector>
#include<queue>
using namespace std;
vector<int> edge[501];      // 邻接链表,只保存与其相邻的结点编号 
queue<int> Q;               // 保存入度为0的结点的队列 
int main()
{
    int inDegree[501];      // 统计每个结点的入度 
    int n,m;
    while(scanf("%d%d",&n,&m)!=EOF){
        if(n==0 && m==0)  break;
        for(int i=0;i<n;i++){    // 初始化所有结点,0~n-1 
            inDegree[i]=0;       // 初始化入度信息,所有节点的入度均为0
            edge[i].clear();     // 清空邻接链表   
        } 
        while(m--){
            int a,b;
            scanf("%d%d",&a,&b);   // 读入一条a指向b的有向边 
            inDegree[b]++;         // 又出现了一条弧头指向b的边,累加结点b的入度 
            edge[a].push_back(b);  // 将b加入a的邻接链表 
        }
        while(Q.empty()==false)  Q.pop();   // 若队列非空,则一直弹出队头元素,即清空队列
        for(int i=0;i<n;i++){               // 统计所有结点的入度 
            if(inDegree[i]==0)  Q.push(i);  // 若结点入度为0,将其放入队列 
        } 
        int cnt=0;                  // 累加已确定拓扑序列的结点个数 
        while(Q.empty()==false){    // 当队列中入度为0的结点未被取完时,重复 
            int nowP=Q.front();     // 读出队列结点编号
            Q.pop();                // 弹出队头元素
            cnt++;                  // 被确定的结点个数加1
            for(int i=0;i<edge[nowP].size();i++){  // 将该结点以及以其为弧尾的所有边去除 
                inDegree[edge[nowP][i]]--;         // 去除某边后,该边所指后继结点入度减1 
                if(inDegree[edge[nowP][i]]==0){    // 若该结点入度变为0,将其放入队列中 
                    Q.push(edge[nowP][i]);    
                }
            } 
        } 
        if(cnt==n)  puts("YES");          // 若所有结点多能被确定拓扑序列,则原图为有向无环图 
        else puts("NO"); 
    } 
    return 0;    
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值