• 暑假集训Day7 D(拓扑排序判环)


    题目链接在这里:Problem - D - Codeforces

    拓扑排序是个好东西,常用在途中各个点之间有先后顺序的问题的求解,同时在处理环问题中也有应用。在处理与环有关的问题时可以直接去掉与环无关的点,相当于在不断的简化这个图,不断通过入度为0的点删根节点,直到没有入度为0 的点,剩下的点全在环里面。删边的话直接将边所指向点的入度减一就行了。

    以前遇到环的问题一般想的是tarjan,不过tarjan需要遍历边,而且删边的话只能对每一条边进行操作,需要枚举边,这里边数远远大于点数,所以用tarjan是不合适的。点的数量级小的话,用拓扑排序判断环是一个很好的选择。

     1 #include "bits/stdc++.h"
     2 using namespace std;
     3 const int MAX=505;
     4 int n,m;
     5 int a[MAX][MAX];
     6 int in[MAX],ii[MAX];
     7 bool topu(){
     8     int i,j,zt,an=0;
     9     queue <int> q;
    10     while (!q.empty()) q.pop();
    11     for (i=1;i<=n;i++)
    12         if (ii[i]==0)
    13             q.push(i),an++;
    14     while (!q.empty()){
    15         zt=q.front();q.pop();
    16         for (i=1;i<=n;i++)
    17             if (a[zt][i] && ii[i]){
    18                 ii[i]--;
    19                 if (ii[i]==0) q.push(i),an++;
    20             }
    21     }
    22     return (an==n);
    23 }
    24 int main(){
    25     freopen ("d.in","r",stdin);
    26     freopen ("d.out","w",stdout);
    27     int i,j,u,v;
    28     scanf("%d%d",&n,&m);
    29     memset(a,0,sizeof(a));
    30     memset(in,0,sizeof(in));
    31     for (i=1;i<=m;i++){
    32         scanf("%d%d",&u,&v);
    33         a[u][v]=1;
    34         in[v]++;
    35     }
    36     for (i=1;i<=n;i++){
    37         for (j=1;j<=n;j++) ii[j]=in[j];
    38         ii[i]--;
    39         if (topu()){
    40             printf("YES");
    41             return 0;
    42         }
    43     }
    44     printf("NO");
    45     return 0;
    46 }
    未来是什么样,未来会发生什么,谁也不知道。 但是我知道, 起码从今天开始努力, 肯定比从明天开始努力, 要快一天实现梦想。 千里之行,始于足下! ——《那年那兔那些事儿》
  • 相关阅读:
    深入理解CSS中的margin负值
    深入理解CSS浮动
    深入理解CSS绝对定位
    深入理解display属性
    JAVA-初步认识-第四章-内存空间的划分&栈内存&堆内存
    JAVA-初步认识-第四章-数组-概述和定义
    JAVA-初步认识-第四章-重载练习
    JAVA-初步认识-第四章-重载
    JAVA-初步认识-第四章-函数-内存加载过程
    JAVA-初步认识-第一章-整体的认识
  • 原文地址:https://www.cnblogs.com/keximeiruguo/p/15037754.html
Copyright © 2020-2023  润新知