复习笔记2:拓扑排序可判断有向图是否存在环
/**
1.求拓扑排序的序列
2.求关键路径:
广域网成整个工程所需的时间取决于从源点到汇点的最长路径长度。
路径长度等于路径上各边的权之和。这条具有最大长度的路径就叫做关键路径
(拓扑排序可以判断有向图是否有环)
(并查集可以判断无向图是否有环,若merge(..)的时候,两个节点已经在同一个连通分支时,则表示有环)
输入://4 1 3
7 8
1 2 1
1 3 2
1 4 1
2 5 1
3 5 4
4 6 3
5 7 5
6 7 2
**/
#include<iostream>
#include<vector>
#include<list>
#define MAX_N 100
using namespace std;
struct Node
{
int num;
int cost;
};
struct Edge
{
int d;//入度
vector<Node> v;
};
Edge edge[MAX_N];
int n,m;
list<int> ls;
void getTopOrder();
void getKeyRoad();
int main()
{
cin>>n>>m;
Node nod;
for(int i=0;i<=n;i++)
{
edge[i].d=0;
}
for(int i=0;i<m;i++)
{
int a,b,val;
cin>>a>>b>>val;
nod.num=b;
nod.cost=val;
edge[a].v.push_back(nod);
edge[b].d++;
}
getTopOrder();
getKeyRoad();
return 0;
}
void getTopOrder()
{
vector<Node> vt;
int counts=0;
for(int i=1;i<=n;i++)
{
if(edge[i].d==0)
{
counts++;
cout<<i<<" ";
ls.push_back(i);
edge[i].d=-1;
vt=edge[i].v;
for(int j=0;j<vt.size();j++)
{
edge[vt[j].num].d--;
}
i=0;
}
}
if(counts==0)
{
cout<<"图中有环!"<<endl;
}
}
void getKeyRoad()
{
int e[MAX_N],l[MAX_N];
for(int i=1;i<=n;i++)e[i]=0;
vector<Node> vt;
list<int > l1=ls;
while(!l1.empty())
{
int i=l1.front();
l1.pop_front();
vt=edge[i].v;
for(int j=0;j<vt.size();j++)
{
if(e[vt[j].num]<e[i]+vt[j].cost)
{
e[vt[j].num]=e[i]+vt[j].cost;
}
}
}
l[n]=e[n];
l1=ls;
while(!l1.empty())
{
int i=l1.back();
l1.pop_back();
vt=edge[i].v;
for(int j=0;j<vt.size();j++)
{
if(l[i]>l[vt[j].num]-vt[j].cost)
{
l[i]=l[vt[j].num]-vt[j].cost;
}
}
}
cout<<endl;
for(int i=1;i<=n;i++)cout<<e[i]<<" ";
cout<<endl;
for(int i=1;i<=n;i++)cout<<l[i]<<" ";
//若e[i]和l[i]相等,i就是关键路径上的点
cout<<endl;
for(int i=1;i<=n;i++)
{
if(e[i]==l[i])cout<<i<<" ";
}
}
关键路径的空间复杂度分析