zoukankan      html  css  js  c++  java
  • ACwing848. 有向图的拓扑序列

    题目

    给定一个n个点m条边的有向图,点的编号是1到n,图中可能存在重边和自环。

    请输出任意一个该有向图的拓扑序列,如果拓扑序列不存在,则输出-1。

    若一个由图中所有点构成的序列A满足:对于图中的每条边(x, y),x在A中都出现在y之前,则称A是该图的一个拓扑序列。

    输入格式

    第一行包含两个整数n和m

    接下来m行,每行包含两个整数x和y,表示存在一条从点x到点y的有向边(x, y)。

    输出格式

    共一行,如果存在拓扑序列,则输出任意一个合法的拓扑序列即可。

    否则输出-1。

    数据范围

    1n,m105

    输入样例:
    3 3
    1 2
    2 3
    1 3
    
    输出样例:
    1 2 3
    

    分析

    拓扑排序,就是找入度为0的点入队列,弹出队列后将其出边连接点的入度减一。写法和BFS的模板差不多,因为都是对队列弹出结点的出边的结点操作。区别:队列弹出结点信息要记录,因为弹出结点的顺就是拓扑排序顺序。可以开一个数组记录弹出结点的信息,或者用数组模拟队列。

    整体思路:

    1.先找到所有入度为0 的结点入队列q

    2.弹出队头元素q.front(),并记录这个结点

    3.找到这个结点的所有出边的结点,使这些结点的入度减一,若入度减一后为0,入队列。

    4.循环2,3步直到队列为空

    代码

    用 ans存放拓扑排序结果

     1 #include<iostream>
     2 #include<algorithm>
     3 #include<cstring>
     4 #include<queue>
     5 using namespace std;
     6 
     7 const int N = 100010;
     8 int h[N],e[N],ne[N],idx;
     9 int n,m;
    10 int d[N];//存放每个结点的入度
    11 vector<int>ans;//记录拓扑排序结果
    12 
    13 void add(int a,int b){
    14     e[idx] = b,ne[idx] = h[a],h[a] = idx++;
    15 }
    16 
    17 void topsort(){
    18     queue<int>q;
    19     //寻找度为0的点
    20     for(int i = 1;i <=n;i++){
    21         if(d[i] == 0){
    22             q.push(i);
    23         }
    24     }
    25     
    26     while(!q.empty()){
    27         int t = q.front();ans.push_back(t);
    28         q.pop();
    29         //将该元素出边的结点入度减一
    30         for(int i = h[t];i!=-1;i = ne[i]){
    31             int j = e[i];
    32             d[j]--; //删掉边,入度减一
    33             if(d[j] == 0){
    34                 q.push(j);
    35             }
    36         }
    37     }
    38     
    39 }
    40 
    41 int main(){
    42     scanf("%d%d",&n,&m);
    43     memset(h,-1,sizeof(h));
    44     for(int i = 0;i < m;i++){
    45         int a,b;
    46         scanf("%d%d",&a,&b);
    47         add(a,b);
    48         d[b]++; //b的入度加1
    49     }
    50     topsort();
    51     if(ans.size()!=n){
    52         cout<<"-1";
    53     }else{
    54         for(auto it:ans) cout<<it<<" ";
    55     }
    56     return 0;
    57 }

    用数组模拟队列,这样会保留弹出结点信息

     1 #include<iostream>
     2 #include<algorithm>
     3 #include<cstring>
     4 using namespace std;
     5 
     6 const int N = 100010;
     7 int h[N],e[N],ne[N],idx;
     8 int n,m;
     9 int d[N];//存放每个结点的入度
    10 int q[N]; //用数组模拟队列
    11 
    12 void add(int a,int b){
    13     e[idx] = b,ne[idx] = h[a],h[a] = idx++;
    14 }
    15 
    16 bool topsort(){
    17     int hh = 0, tt = -1;  //定义对头,队尾
    18     //寻找度为0的点
    19     for(int i = 1;i <=n;i++){
    20         if(d[i] == 0){
    21             q[++tt] = i;  //入队
    22         }
    23     }
    24     
    25     while(hh <= tt){
    26         int t = q[hh++];
    27         
    28         //将该元素出边的结点入度减一
    29         for(int i = h[t];i!=-1;i = ne[i]){
    30             int j = e[i];
    31             d[j]--; //删掉边,入度减一
    32             if(d[j] == 0){
    33                 q[++tt] = j;
    34             }
    35         }
    36     }
    37     return tt == n-1; //是否队列为n个点,来判断是否存在拓扑序列
    38     
    39 }
    40 
    41 int main(){
    42     scanf("%d%d",&n,&m);
    43     memset(h,-1,sizeof(h));
    44     for(int i = 0;i < m;i++){
    45         int a,b;
    46         scanf("%d%d",&a,&b);
    47         add(a,b);
    48         d[b]++; //b的入度加1
    49     }
    50    if(topsort()){
    51        for(int i = 0;i < n;i++)
    52         printf("%d ",q[i]);
    53    }else{
    54        printf("-1");
    55    }
    56     return 0;
    57 }
  • 相关阅读:
    倍福TwinCAT(贝福Beckhoff)常见问题(FAQ)-如何添加Scope监控
    倍福TwinCAT(贝福Beckhoff)常见问题(FAQ)-如何使用随机数DRAND模块
    倍福TwinCAT(贝福Beckhoff)常见问题(FAQ)-如何使用断点
    倍福TwinCAT(贝福Beckhoff)常见问题(FAQ)-如何实现开平方的Pow函数
    倍福TwinCAT(贝福Beckhoff)常见问题(FAQ)-如何声明定时器,使用定时器TON模块 TC3
    倍福TwinCAT(贝福Beckhoff)常见问题(FAQ)-如何声明定时器,使用定时器TON模块 TC2
    java中配置自定义拦截器中exclude-mapping path是什么意思?
    java web 过滤器跟拦截器的区别和使用
    利用jquery.validate异步验证用户名是否存在
    jquery统计显示或隐藏的元素个数
  • 原文地址:https://www.cnblogs.com/fresh-coder/p/14441860.html
Copyright © 2011-2022 走看看