拓扑排序理解

前提:

将拓扑排序首先要简单介绍一下AOV网。AOV网指的是顶点表示活动,有向边表示活动之间的次序(比如:a->b指的是a发生后b才可以发生)。可以将AOV网联想到一个建筑的施工图(A:买材料,B:打地基,C:盖楼)就可以有一个简单的图:A->B->C;先买材料再打地基然后盖楼。

拓扑排序理解:

首先拓扑排序的定义:对一个有向无环图进行拓扑排序,然后最终得到的序列满足如果U可以按照图到达V,则U肯定在V之前。对应的到的序列也叫拓扑排序列。
回到上面的例子,该例子对应的拓扑排序列就是 A,B,C。这里简单说一下我的理解:拓扑排序是为了得到一个活动有序发生发生的顺序,所以起点肯定是该活动没有依赖的活动(没有其它点指向它,也就是入度为0);
这里肯定会有读者会想到,假如这个图是个环咋搞?也就是没有入度为0的点。
哈哈哈哈 那就不搞,所以再提一下就是拓扑排序的前提是该图没有环。因此拓扑排序也衍生出一个功能:判断一个图是否有环。(如果一个图拓扑排序失败,那么证明该图有环)

实现过程:

我们现总结一下前提条件哈:
首先是基于图的排序,那么条件一是需要一个图(有点废话ORZ)。
然后需要从入度为0的点开始,所以条件二是所有点的入度(一个数组);
code:

int in[50];
vector<vector<int> >graph(50,vector<int>(0,0));

完事!!!so easy!
过程:
我们得到了图(vector<vector >graph)和若干个开始点(一个queue),那么我们先从开始点进行迭代。
1.把开始点取出并将开始点所有可以直接到达的点入度减一。
2.如果到达的点入度为0也成为一个新的开始点,放回到queue里。
3.当queue不为空一直循环执行。
code:

	queue<int >myq;
    for(int i=0;i<50;i++){
        if(in[i]==0){
            myq.push(i);
        }
    }
    //负责记录序列;
    vector<int>ans;
    while(!myq.empty()){
        int num=myq.top();
        myq.pop();
        int len=graph[num].size();
        for(int i=0;i<len;i++){
            int point=graph[num][i];
            in[point]--;
            if(in[point]==0){
                myq.push(point);
            }
        }
        ans.push_back(num);
    }

注:是不是很像bfs~~;

例题:

拓扑排序例题
注:这道题要求字典序所以得适用priority_queue;
ac code:

#include<bits/stdc++.h>
using namespace std;

    int in[50];
int main(){
    char s[5];
    vector<vector<int> >graph(50,vector<int>(0,0));
    set<int>judge;
    while(cin>>s){
        int left=s[0]-'A';
        int right=s[2]-'A';
        judge.insert(left);
        judge.insert(right);
        if(s[1]=='>'){
            in[right]++;
            graph[left].push_back(right);
        }else{
            in[left]++;
            graph[right].push_back(left);
        }
    }
    priority_queue<int,vector<int>,greater<int> >myq;
    for(int i=0;i<50;i++){
        if(in[i]==0&&judge.find(i)!=judge.end()){
            myq.push(i);
        }
    }
    vector<int>ans;
    while(!myq.empty()){
        int num=myq.top();
        myq.pop();
        int len=graph[num].size();
        for(int i=0;i<len;i++){
            int point=graph[num][i];
            in[point]--;
            if(in[point]==0){
                myq.push(point);
            }
        }
        ans.push_back(num);
    }
    if(ans.size()!=judge.size()){
        cout<<"No Answer!"<<endl;
    }else{
        for(int i=0;i<ans.size();i++){
          //  cout<<ans[i]+'A'<<endl;
            printf("%c",ans[i]+'A');
        }
        printf("\n");
    }

    return 0;
}

随笔:

已经大四了,大学时光就快没了。难受!!!
希望雷火和拼多多能尽快下来意向书吧,以及阿里腾讯再捞一手吧~~

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值