前提:
将拓扑排序首先要简单介绍一下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;
}
随笔:
已经大四了,大学时光就快没了。难受!!!
希望雷火和拼多多能尽快下来意向书吧,以及阿里腾讯再捞一手吧~~