AOE网上的关键路径

    一个无环的有向图称为无环图(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;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值