zoukankan      html  css  js  c++  java
  • 拓扑排序

    拓扑排序

    典例1:有向图的拓扑序列

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

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

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

    输入格式

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

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

    输出格式

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

    否则输出 −1。

    数据范围

    1≤n,m≤10^5

    输入样例:

     3 3
     1 2
     2 3
     1 3

    输出样例:

     1 2 3

    code:

     #include<cstdio>
     #include<cstring>
     #include<iostream>
     #include<algorithm>
     using namespace std;
     
     const int N = 1e5 + 10;
     int e[N],ne[N],h[N],q[N],d[N];
     int n,m,idx;
     void add(int a,int b){
         e[idx] = b;
         ne[idx] = h[a];
         h[a] = idx++;
     }
     
     bool topsort(){
         int hh = 0,tt = -1;
         for(int i=1;i<=n;i++)
             if(!d[i])
                 q[++tt] = i;
         while(hh <= tt){
             int t = q[hh++];
             for(int i=h[t];i!=-1;i=ne[i]){
                 int j = e[i];
                 d[j]--;
                 if(!d[j])
                     q[++tt] = j;
            }
        }
         return tt == n-1;
     }
     int main(){
         cin>>n>>m;
         memset(h,-1,sizeof h);
         while(m--){
             int a,b;
             cin>>a>>b;
             add(a,b);
             d[b]++;
        }
         if(topsort()){
             for(int i=0;i<n;i++) printf("%d ",q[i]);
             puts("");
        }else{
             puts("-1");
        }
         return 0;
     }

    典例2:

    问题描述:

    原题链接

    code: #include<set> #include<map>

     #include<cstdio>
     #include<cstring>
     #include<iostream>
     #include<algorithm>
     using namespace std;
     
     const int N = 1e5 + 10;
     int h[N],e[N],ne[N],d[N],q[N];
     int t,idx;
     int indx;
     void add(int x,int y){//数组模拟邻接表存储图
      e[idx] = y;
      ne[idx] = h[x];
      h[x] = idx++;
     }
     
     void topsort(){
      int hh = 0,tt = -1;
      for(int i=1;i<indx;i++)
      if(!d[i])
      q[++tt] = i;
      //队列 类似宽搜思想找入度为0的点
      while(hh <= tt){
      int g = q[hh++];
      for(int i = h[g];i!=-1;i=ne[i]){
      int j = e[i];
      d[j]--;
      if(!d[j])
      q[++tt] = j;
      }
      }
     }
     int main(){
      scanf("%d",&t);
      int col;
      for(int i=0;i<t;i++){
      scanf("%d",&col);
     
      /*==================================*/
      //处理每组数据前,先将各种容器、变量初始化,防止组间干扰
      memset(h,-1,sizeof h);
      memset(e,0,sizeof e);
      memset(ne,0,sizeof ne);
      memset(d,0,sizeof d);
      memset(q,0,sizeof q);
      idx = 0;
      indx = 1;
      set<string>have;
      map<int,string>mp;
      map<string,int>pm;
      /*==================================*/
     
      for(int i=0;i<col;i++){
      string name1,name2;
      cin>>name1>>name2;
     
      if(have.count(name1)==0){
      have.insert(name1);
      pm[name1] = indx;//建立姓名与索引的联系。
      mp[indx++] = name1;//建立姓名与索引的联系。
      }
     
      if(have.count(name2)==0){
      have.insert(name2);
      pm[name2] = indx;
      mp[indx++] = name2;
      }
     
      int i1 = pm[name1],i2 = pm[name2];
      add(i1,i2);
      d[i2]++;
      }
     
      //进行拓扑排序
      topsort();
     
      for(int i=0;i<indx;i++){
      //被tm格式卡死了,找了大半天,我淦!!
           if(i==indx-1){ 
            cout<<mp[q[i]]<<endl; 
        }else{ 
            cout<<mp[q[i]]<<" "; 
        }  
      }  

    return 0; 
    }

     

  • 相关阅读:
    面向对象
    Spring学习(十四)----- Spring Auto Scanning Components —— 自动扫描组件
    Spring学习(十三)-----Spring 表达式语言(Spring EL)
    Spring学习(十二)-----Spring @PostConstruct和@PreDestroy实例
    Spring学习(十二)-----Spring Bean init-method 和 destroy-method实例
    学习计划
    Spring学习(十一)-----Spring使用@Required注解依赖检查
    Spring学习(十)-----Spring依赖检查
    Spring学习(九)-----Spring bean配置继承
    Spring学习(八)-----Spring注入值到集合类型的例子
  • 原文地址:https://www.cnblogs.com/yuanshixiao/p/14820275.html
Copyright © 2011-2022 走看看