刚开始就拿一个点算,用栈操作
死活只有20分,还是老老实实用拓扑排序的求最晚时间的方法算
恶心的地方是关键路径有很多,,,,,,,,,,,,,
不说了,太难了
#include <bits/stdc++.h>
using namespace std;
#define Inf 2<<17
int A[10000][10000];
int Indegree[10000]={0};
int Outdegree[10000]={0};
int ETime[10000]={0};//最早完成
int LTime[10000]={0}; //最晚完成
int N,M;
int ECT;
int getMax(int a[]){//求一个数组的最大值
int max=-1;
for(int i=1;i<=N;i++){
if(a[i]>max) max=a[i];
}
return max;
}
int TopSort(){
int V,cnt=0;
queue<int> q;
for(int i=1;i<=N;i++){
if(Indegree[i]==0){//找出所有入度为0的点,将他们push进队列中
q.push(i);
}
}
int temp;
while(!q.empty()){
temp=V=q.front(); //找到队列第一个元素
q.pop(); //pop出来
cnt++;
for(int j=1;j<=N;j++){
if(A[V][j]!=Inf){ //与该节点有关系的点
if(ETime[V]+A[V][j]>ETime[j]){
ETime[j]=ETime[V]+A[V][j];//更新最早完成时间
}
if(--Indegree[j]==0){//如果度为0
q.push(j); //把这个点放进队列里
}
}
}
}
ECT=getMax(ETime);
if(cnt!=N) return 0;
return temp;
}
void late(){
int V;
queue<int> q;
for(int i=1;i<=N;i++){
LTime[i]=ECT;
if(Outdegree[i]==0){//找出所有出度为0的点,将他们push进队列中
q.push(i);
}
}
while(!q.empty()){
V=q.front(); //找到队列第一个元素
q.pop(); //pop出来
for(int i=1;i<=N;i++){
if(A[i][V]!=Inf){ //与该节点有关系的点
LTime[i]=min(LTime[i],LTime[V]-A[i][V]);
if(--Outdegree[i]==0){//如果度为0
q.push(i); //把这个点放进队列里
}
}
}
}
}
int main(){
cin>>N>>M;
for(int i=1;i<=N;i++){
for(int j=1;j<=N;j++){
A[i][j]=Inf;// 将每个值初始化为最大值
}
}
for (int i = 0; i < M; ++i)//常规读取
{
int a,b;
cin>>a>>b;
cin>>A[a][b]; //修改完成工作的时间
Indegree[b]++;
Outdegree[a]++;
}
int k=TopSort();
if(!k) printf("0\n");
else{
printf("%d\n",ECT);
late();
for(int i=1;i<=N;++i){
// for(int j=1;j<=N;j++){
for(int j=N;j>=1;j--){//关键活动输出的顺序规则是:任务开始的交接点编号小者优先,起点编号相同时,与输入时任务的顺序相反。
if(A[i][j]!=Inf&&ETime[i]+A[i][j]==LTime[j]){
printf("%d->%d\n",i,j);
}
}
}
}
return 0;
}