题意:背景是计算机组成原理中的指令,即instruction。输入有多个样例,第一行为n和m,n个指令,m个依赖关系,接下来m行,每行为x,y,z,表示x和y之间的安全距离(开始时间之差)是z,y应该在x后执行。CPU每运行一条指令需要1ns,输出执行完所有指令需要的最短CPU运行时间
思路:根据拓扑序列正向逐一求出每个活动的最早开始时间,再根据拓扑序列的逆序列求出每个活动的最晚开始时间,最后最大的最早开始时间即为路径长度,由于每条指令执行时间为1s,所以+1,
还是有几点不太清楚
- 1.看的王道书,为什么CPU执行每条指令1ns,所有的最早开始时间都要初始化为1ns?我没有这么做,是在最后的答案上加了个1,含义是最前的指令从0开始,算出来关键路径的长度,加上最后一条指令执行的1s就是答案,倒是AC了·
- 2.汇点(出度为0)的最晚开始时间初始化时=最早开始时间,原因是,汇点属于关键路径上的点,关键点最早开始时间等于最晚开始时间
#include<iostream>
#include<vector>
#include<cstring>
#include<climits>
#include<queue>
using namespace std;
const int MAXN=1001;
const int INF=INT_MAX;
struct Edge {
int to;
int len;
Edge(int t,int l):to(t),len(l) {}
};
vector<Edge> graph[MAXN];
int inDegree[MAXN];
int earlist[MAXN]; //最早开始时间
int lastest[MAXN]; //最晚开始时间
void Critical(int n) {
vector<int> Topology;
queue<int> q;
for(int i=0; i<n; i++) {
if(inDegree[i]==0) { //源点
q.push(i);
}
}
while(!q.empty()) {
int u=q.front();
Topology.push_back(u);
q.pop();
for(int i=0; i<graph[u].size(); i++) {
int v=graph[u][i].to;
int len=graph[u][i].len;
inDegree[v]--;
if(inDegree[v]==0) {
q.push(v);
}
earlist[v]=max(earlist[v],earlist[u]+len);
}
}
for(int i=Topology.size()-1; i>=0; i--) { //从后往前遍历
int u=Topology[i];
if(graph[u].size()==0){ //出度=0,为汇点
lastest[u]=earlist[u];
}
else{
lastest[u]=INF;
}
for(int i=0; i<graph[u].size(); i++) {
int v=graph[u][i].to;
int len=graph[u][i].len;
lastest[u]=min(lastest[u],lastest[v]-len);
}
}
}
int main() {
int n,m;
while(scanf("%d%d",&n,&m)!=EOF) {
memset(inDegree,0,sizeof(inDegree));
memset(graph,0,sizeof(graph));
for(int i=0; i<n; i++) { //CPU执行一条指令时间为1ns
earlist[i]=0;
}
while(m--) {
int u,v,len;
scanf("%d%d%d",&u,&v,&len);
graph[u].push_back(Edge(v,len));
inDegree[v]++;
}
Critical(n);
int answer=0;
for(int i=0;i<n;i++){
answer=max(answer,earlist[i]);
}
printf("%d\n",answer+1);
}
return 0;
}