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; 
    }

     

  • 相关阅读:
    卸载全部appx应用(包括应用商店)
    重置 Launchpad 和更新APP图标缓存
    删除OSX中第三方的「偏好设置」程序(.prefPane)
    IOS segue(跳转页面处理)
    IOS NSNotificationCenter(通知 的使用)监听文本框的文字改变
    IOS UITextFieldDelegate (常用的代理方法)
    IOS UIActionSheet(底部 弹出框的使用)
    IOS 偏好设置数据 存 取(Preferences文件夹)
    IOS plist的数据 存 取(沙河目录)
    显示 Mac隐藏的文件夹 命令语句
  • 原文地址:https://www.cnblogs.com/yuanshixiao/p/14820275.html
Copyright © 2011-2022 走看看