【计算机考研机试指南】第十一章 图论:关键路径——Instruction Arrangement

emmm还有点疑问,待更新完善。 

#include <iostream>
#include <cstdio>
#include <queue>
#include <vector>
#include <cstring>
#include <climits>

using namespace std;

const int MAXN = 1001;
const int INF = INT_MAX;

struct Edge{
	int to;
	int length;
	Edge(int t, int l): to(t), length(l){
	}
}; 

vector<Edge> graph[MAXN];	//邻接表存储图 
int earliest[MAXN];			//最早开始时间
int lastest[MAXN];			//最晚开始时间
int inDegree[MAXN];			//入度

void CriticalPath(int n){
	vector<int> topology;	//拓扑序列 
	queue<int> node;
	for(int i = 0; i < n; i++){
		if(inDegree[i] == 0){
			node.push(i);
			earliest[i] = 1; 	//最早开始时间初始化为1 
		}
	}
	while(!node.empty()){
		int u = node.front();
		topology.push_back(u);
		node.pop();
		for(int i = 0; i < graph[u].size(); i++){
			int v = graph[u][i].to;
			int l = graph[u][i].length;
			earliest[v] = max(earliest[v], earliest[u] + l);
			inDegree[v]--;
			if(inDegree[v] == 0){
				node.push(v);
			}
		}
	}
	for(int i = topology.size()-1; i >= 0; i--){
		int u = topology[i];
		if(graph[u].size() == 0){
			lastest[u] = earliest[u];	//汇点的最晚开始时间初始化 
		}else{
			lastest[u] = INF;		//非汇点的最晚开始时间初始化 
		}
		for(int j = 0; j < graph[u].size(); j++){
			int v = graph[u][j].to;
			int l = graph[u][j].length;
			lastest[u] = min(lastest[u], lastest[v] - l);
		}
	}	
} 

int main(int argc, char** argv) {
	int n, m;
	
	while(scanf("%d %d", &n, &m) != EOF){
		
		memset(graph, 0, sizeof(graph));
		memset(earliest, 0, sizeof(earliest));
		memset(lastest, 0, sizeof(lastest));
		memset(inDegree, 0, sizeof(inDegree));
		
		while(m--){
			int from, to, length;
			scanf("%d %d %d", &from, &to, &length);
			graph[from].push_back(Edge(to, length));
			inDegree[to]++; 
		}
		
		CriticalPath(n);
		
		int answer = 0;
		for(int i = 0; i < n; i++){
			answer = max(answer, earliest[i]);
		}
		printf("%d\n", answer);
	} 
	
	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值