T46449 有向图无环(DAG)的判定 (dfs)

T46449 有向图无环(DAG)的判定
提交
172
通过
69
时间限制
1.00s
内存限制
125.00MB
提交答案
加入收藏
题目提供者
BDFZ-OIER
难度
暂无评定
历史分数
100
提交记录
标签
暂无标签
进入讨论版
相关讨论
暂无
推荐题目
展开
题目描述
给定无权有向图G(V,E),请判断G是否是一个有向无环图(DAG)。

*在有向图中,若存在B边,则存在环。

输入格式
第一行包含两个整数N、M,表示该图共有N个结点和M条有向边。(N <= 5000,M <= 200000)

接下来M行,每行包含2个整数{u,v},表示有一条有向边(u,v)

输出格式
有环输出“not DAG”,无环输出“DAG”

输入输出样例
输入 #1复制
5 7
1 2
1 5
2 3
3 1
3 2
4 1
4 5
输出 #1复制
not DAG

#include <iostream>
#include <string>
#include <cstring>
#include <algorithm>
#include <cstdio>
#include <vector>
#include <queue>
#include <climits>
#include <stack>
#include <map>
#include <cmath>
#include <set>
using namespace std;
typedef long long ll;
int n,m;
const int maxn=5005;
int post[maxn],pre[maxn];
vector<int>adj[maxn];
template<class T>
void read(T &x){
    ll f=1;
    x=0;
    char c=getchar();
    while(!isdigit(c)){
        f=-1;
        c=getchar();
    }
    while(isdigit(c)){
        x=x*10+c-48;
        c=getchar();
    }
    x*=f;
}
template<class T>
void write(T x){
    if(x<0){
        putchar('-');
        x=-x;
    }
    if(x>9){
        write(x/10);
    }
    putchar(x%10+'0');
}
#define ios ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
int flag=1,t;
void dfs(int u){
   pre[u]=++t;
   for(auto i:adj[u]){
       if(!pre[i]){
           dfs(i);
       }
       else if(!post[i]){
           flag=0;
       }
   }
   post[u]=++t;
}
int main()
{  
    
    read(n);
    read(m);
    int a,b;
    for(int i=0;i<m;i++){
        read(a),read(b);
        adj[a].push_back(b);
    }
    for(int i=1;i<=n;i++){
        if(!pre[i])dfs(i);
    }
    if(flag)printf("DAG");
    else printf("not DAG");
    return 0;
}
可以使用拓扑排序来判断一个有向图是否为DAG。 具体步骤如下: 1. 统计每个顶点的入度,存储在数组indegree中。 2. 将入度为0的顶点加入队列queue中。 3. 取出队头顶点u,并将其从图中删除,即将u所能到达的所有顶点的入度减1。如果有某个顶点的入度减为0,则将其加入队列queue中。 4. 重复步骤3,直到队列queue为空。 5. 如果图中还有顶点没有被删除,则说明图中存在环,即不是DAG。 代码实现如下: ```c #include <stdio.h> #include <stdlib.h> #define MAXV 100 // 最大顶点数 typedef struct node{ int v; // 顶点编号 struct node *next; // 指向下一个邻接点 }Node; Node* graph[MAXV]; // 邻接表 int indegree[MAXV]; // 入度数组 int isDAG(int n) // 判断是否为DAG { int i, v, count = 0; Node *p; int queue[MAXV], front = 0, rear = 0; // 初始化入度数组和邻接表 for(i = 0; i < n; i++){ indegree[i] = 0; graph[i] = NULL; } // 读入图的边信息,建立邻接表和入度数组 while(scanf("%d", &v) != EOF){ Node *newnode = (Node*)malloc(sizeof(Node)); newnode->v = v; newnode->next = graph[i]; graph[i] = newnode; indegree[v]++; } // 将所有入度为0的顶点加入队列 for(i = 0; i < n; i++){ if(indegree[i] == 0){ queue[rear++] = i; } } // 拓扑排序 while(front != rear){ v = queue[front++]; count++; for(p = graph[v]; p != NULL; p = p->next){ indegree[p->v]--; if(indegree[p->v] == 0){ queue[rear++] = p->v; } } } // 判断是否为DAG if(count == n){ return 1; }else{ return 0; } } int main() { int n; // 顶点数 scanf("%d", &n); if(isDAG(n)){ printf("It is a DAG!\n"); }else{ printf("It is not a DAG!\n"); } return 0; } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值