输入:有向图(顶点序列,有向边序列)
功能要求:能判断是否是AOE 网;输出各关键活动或输出关键路径(包括关键路径的长度)
求AOE中关键路径和关键活动的算法思想:
① 利用拓扑排序求出AOE网的一个拓扑序列;
② 从拓扑排序的序列的第一个顶点(源点)开始,按拓扑顺序依次计算每个事件的最早发生时间ve(i) ;
③ 从拓扑排序的序列的最后一个顶点(汇点)开始,按逆拓扑顺序依次计算每个事件的最晚发生时间vl(i) ;
抽象数据模型
struct node
{
int v, cost;
node(int _v, int _cost): v(_v), cost(_cost) {}
};
#include<iostream>
#include<algorithm>
#include<vector>
#include<queue>
#include<stack>
#define maxn 1000
using namespace std;
struct node
{
int v, cost;
node(int _v, int _cost): v(_v), cost(_cost) {}
};
int ve[maxn];
int vl[maxn];
int n, m;
int indegree[maxn];
vector<node> adj[maxn];
vector<int> path[maxn];
stack<int> s;
int j = 0; //汇点的编号
bool topologicalsort()
{
queue<int> q;
for(int i = 1; i <= n; i++)
{
if(indegree[i] == 0)
{
q.push(i);
}
}
while(!q.empty())
{
int u = q.front();
q.pop();
s.push(u);
for(int i = 0; i < adj[u].size(); i++)
{
int v = adj[u][i].v;
indegree[v]--;
if(indegree[v] == 0)
{
q.push(v);
}
if(ve[u] + adj[u][i].cost > ve[v])
{
ve[v] = ve[u] + adj[u][i].cost;
}
}
}
if(s.size() == n) return true;
else return false;
}
int criticalpath()
{
fill(ve, ve+maxn, 0);
if(!topologicalsort()) return -1;
int maxlength = 0;
for(int i = 1; i <= n; i++)
{
if(ve[i] > maxlength)
{
maxlength = ve[i];
j = i;
}
}
fill(vl, vl+maxn, maxlength);
while(!s.empty())
{
int u = s.top();
s.pop();
for(int i = 0; i < adj[u].size(); i++)
{
int v = adj[u][i].v;
if(vl[v] - adj[u][i].cost < vl[u])
{
vl[u] = vl[v] - adj[u][i].cost;
}
}
}
for(int u = 1; u <= n; u++)
{
for(int i = 0; i < adj[u].size(); i++)
{
int v = adj[u][i].v;
int cost = adj[u][i].cost;
int e = ve[u], l = vl[v] - cost;
if(e == l)
{
//printf("%d --> %d\n",u, v);
path[u].push_back(v);
}
}
}
return ve[j];
}
vector<int> temppath;
void dfs(int v)
{
if(v == j)
{
temppath.push_back(v);
for(int i = 0; i < temppath.size() -1; i++)
{
printf("%d --> ",temppath[i]);
}
printf("%d\n",temppath[temppath.size() -1]);
temppath.pop_back();
return;
}
temppath.push_back(v);
for(int i = 0; i < path[v].size(); i++)
{
dfs(path[v][i]);
}
temppath.pop_back();
}
int main()
{
printf("请输入顶点数和边数:");
scanf("%d%d",&n, &m);
int u1, v1, w1;
printf("依次输入起点、终点、权值:\n");
for(int i = 0; i < m; i++)
{
scanf("%d%d%d",&u1, &v1, &w1);
adj[u1].push_back(node(v1, w1));
indegree[v1]++;
}
int ans = criticalpath();
printf("关键路径长度为:%d\n",ans);
printf("\n");
for(int i = 1; i <= n; i++)
{
printf("ve[%d] = %d, vl[%d] = %d\n",i, ve[i], i, vl[i]);
}
int vs; //找源点
for(int i = 1; i <= n; i++)
{
if(ve[i] == 0)
{
vs = i;
break;
}
else continue;
}
printf("\n");
//printf("关键路径为:\n");
dfs(vs);
return 0;
}