//时间复杂度(n+e) n:顶点数 e:边数 #include<cstdio> #include<vector> #include<queue> #include<stack> using namespace std; const int MAXN=10000; struct Node{ int x; int v; }; vector<Node> Map[MAXN]; stack<int> num,T; //T为拓扑序列顶点栈,num为零入度顶点栈 int cnt[MAXN],ve[MAXN],vm[MAXN]; //cnt表示各个顶点当前的入度,ve表示各个顶点事件的最早发生时间 //vm表示各个顶点事件的最迟发生时间 int n,m; bool Topo() { int i,j,count=0; Node tmp; while(!T.empty()) T.pop(); while(!num.empty()) num.pop(); for(i=1;i<=n;i++) { if(cnt[i]==0) num.push(i); } while(!num.empty()) { T.push(num.top()); num.pop(); ++count; for(i=0;i<Map[T.top()].size();i++) { tmp=Map[T.top()][i]; cnt[tmp.x]--; if(cnt[tmp.x]==0) num.push(tmp.x); if(ve[tmp.x]<tmp.v+ve[T.top()]) ve[tmp.x]=tmp.v+ve[T.top()]; } } if(count<n) return false; return true; } bool CriticalPath() { int i,j; Node tmp; if(Topo()==false) return false; for(i=1;i<=n;i++) //初始化顶点事件的最迟发生时间 vm[i]=ve[n]; while(!T.empty()) //按拓扑逆序求各顶点的vm值 { j=T.top(); T.pop(); for(i=0;i<Map[j].size();i++) { tmp=Map[j][i]; if(vm[j]>vm[tmp.x]-tmp.v) vm[j]=vm[tmp.x]-tmp.v; } } printf("\n"); for(i=1;i<=n;i++) //求关键活动 { for(j=0;j<Map[i].size();j++) { tmp=Map[i][j]; if(ve[i]==vm[tmp.x]-tmp.v) printf("%d %d %d\n",i,tmp.x,tmp.v); //输出关键路径 } } } int main() { int i,j,a; Node tmp; while(scanf("%d%d",&n,&m)==2) { for(i=1;i<=n;i++) { Map[i].clear(); cnt[i]=0; ve[i]=0; } for(i=1;i<=m;i++) { scanf("%d%d%d",&a,&tmp.x,&tmp.v); Map[a].push_back(tmp); cnt[tmp.x]++; //求各定点的入度 } if(CriticalPath()==false) printf("ERROR\n"); else { printf("\n"); for(i=1;i<=n;i++) { printf("%d %d %d\n",i,ve[i],vm[i]); } } } return 0; }