一个无环的有向图称为无环图(Directed Acyclic Graph),简称DAG图。
AOE(Activity On Edge)网:顾名思义,用边表示活动的网,当然它也是DAG。与AOV不同,活动都表示在了边上,如下图所示:
如上所示,共有11项活动(11条边),9个事件(9个顶点)。整个工程只有一个开始点和一个完成点。即只有一个入度为零的点(源点)和只有一个出度为零的点(汇点)。
关键路径:是从开始点到完成点的最长路径的长度。路径的长度是边上活动耗费的时间。如上图所示,1 到2 到 5到7到9是关键路径(关键路径不止一条,请输出字典序最小的),权值的和为18。
Input
这里有多组数据,保证不超过10组,保证只有一个源点和汇点。输入一个顶点数n(2<=n<=10000),边数m(1<=m <=50000),接下来m行,输入起点sv,终点ev,权值w(1<=sv,ev<=n,sv != ev,1<=w <=20)。数据保证图连通。
Output
关键路径的权值和,并且从源点输出关键路径上的路径(如果有多条,请输出字典序最小的)。
Example Input
9 11 1 2 6 1 3 4 1 4 5 2 5 1 3 5 1 4 6 2 5 7 9 5 8 7 6 8 4 8 9 4 7 9 2
Example Output
18 1 2 2 5 5 7 7 9
一开始我以为源点是1,汇点是n,一直WA... 这下算是彻底理解AOE了
#include <iostream>
#include <cstring>
#include <cstdio>
#include <vector>
#include <stack>
#include <queue>
using namespace std;
const int N = 1e4 + 5;
struct Node {
int v, w;
Node(int v, int w): v(v), w(w){}
};
int ve[N], vl[N], indeg[N], outdeg[N];
int n, m, in, out;
bool vis[N], flag;
vector<Node> g[N];
stack<int> topo;
void DFS(int x) {
if(x == out)
{
flag = true;
return;
}
vis[x] = 1;
printf("%d ", x);
for(int i = 0; i < g[x].size(); i++)
{
int v = g[x][i].v, w = g[x][i].w;
int e = ve[x], l = vl[v] - w;
if(e == l && !flag)
{
printf("%d\n", v);
DFS(v);
}
}
}
void Topological() {
queue<int> q;
memset(ve, 0, sizeof(ve));
q.push(in);
while(!q.empty())
{
int u = q.front();
topo.push(u);
q.pop();
for(int i = 0; i < g[u].size(); i++)
{
int v = g[u][i].v;
indeg[v]--;
if(indeg[v] == 0)
q.push(v);
if(ve[u] + g[u][i].w > ve[v])
ve[v] = ve[u] + g[u][i].w;
}
}
}
void VitalPath() {
Topological();
fill(vl, vl + n + 1, ve[out]);
while(!topo.empty())
{
int u = topo.top();
topo.pop();
for(int i = 0; i < g[u].size(); i++)
{
int v = g[u][i].v;
if(vl[v] - g[u][i].w < vl[u])
vl[u] = vl[v] - g[u][i].w;
}
}
printf("%d\n", ve[out]);
memset(vis, 0, sizeof(vis));
flag = false;
DFS(in);
}
int main(){
int a, b, c;
while(~scanf("%d%d", &n, &m))
{
for(int i = 0; i <= n; i++)
g[i].clear();
memset(indeg, 0, sizeof(indeg));
memset(outdeg, 0, sizeof(outdeg));
while(m--)
{
scanf("%d%d%d", &a, &b, &c);
g[a].push_back(Node(b, c));
indeg[b]++;
outdeg[a]++;
}
for(int i = 1; i <= n; i++)
{
if(indeg[i] == 0) in = i;
if(outdeg[i] == 0) out = i;
}
VitalPath();
}
return 0;
}