拓扑排序

拓扑排序

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

 

posted @ 2021-05-27 23:15  how_you_make_me_feel  阅读(155)  评论(0编辑  收藏  举报