这问题几乎耗了我一下午的时间,一开始自己用邻接矩阵求,但求着求着就感到不对劲了,我怎么知道我所求得这个顺序就是数据所表示的图的顺序呢?我的ve,vl,ee,el是根据什么样的顺序求得呢?好像我自己都不知道。。。
想了想还得是要按拓扑序来做,但我所知道的拓扑序没有权值,而且也只是会输出一个序列而已,存储序列很简单,但要怎么利用存储的这个序列求这四个数组呢?
最后实在是有点烦了,看了题解,也是用邻接矩阵求的,而且也实现了利用拓扑序求ve,vl数组,然后只要看看ve和vl中的数组相等的下标所构成的序列就是关键路径(前提只有一条关键路径),为什么可以不用求ee和el呢?其实我们想一下,ee是活动a[i](a[i]是由<k1,j1>表示)最早的开始时间,那么ee[i]就是ve[k1],而el是活动a[i](a[i]是由<k2,j2>表示),那么el[i]就是vl[j2]-edge[k2][j2];
如果第i条边是关键活动的话,那么他是ee[i]==el[i];也就是ve[k1]==vl[j2]-edge[k2][j2],而k1==k2,j1==j2,所以前面那个式子就是ve[k1]+edge[k1][j1]==vl[j1],即ve[j1]==vl[j1];
所以只要求出ve和vl中的数组相等的下标所构成的序列即可,这个序列就是关键路径
#include<bits/stdc++.h>
using namespace std;
int main(){
//freopen("in.txt","r",stdin);
int mp[110][110];
memset(mp,-1,sizeof(mp));
int a,b,val,v,l;
cin>>v>>l;
for(int i=1;i<=l;i++){//邻接矩阵
cin>>a>>b>>val;
mp[a][b]=val;
}
int k;
int in[110],out[110],ve[110],vl[110];
memset(ve,0,sizeof(ve));
for(int i=1;i<=v;i++){//计算入度
k=0;
for(int j=1;j<=v;j++){
if(mp[j][i]!=-1)
k++;
}
in[i]=k;
}
for(int i=1;i<=v;i++){//计算出度
k=0;
for(int j=1;j<=v;j++){
if(mp[i][j]!=-1)
k++;
}
out[i]=k;
}
for(int i=1;i<=v;i++){//顺拓扑序求ve数组
if(in[i]==0){
for(int j=1;j<=v;j++){
if(mp[i][j]!=-1){
ve[j]=max(ve[j],mp[i][j]+ve[i]);
in[j]--;
}
}
}
}
k=v;
for(int i=1;i<=v;i++) vl[i]=ve[k];
//将vl中的每个顶点初始化为最后一个顶点的值
//因为最后一个顶点是最大值,到后面好更新
for(int i=k;i>=1;i--){//逆拓扑序求vl
if(out[i]==0){
for(int j=1;j<=v;j++){
if(mp[j][i]!=-1){
vl[j]=min(vl[j],vl[i]-mp[j][i]);
out[j]--;
}
}
}
}
cout << "****************************\n";
cout << "Ve数组:";
for(int i = 1; i <= k; i++){
cout << ve[i] << " ";
}
cout << endl;
cout << "Vl数组:";
for(int i = 1; i <= k; i++){
cout << vl[i] << " ";
}
cout << "\n****************************\n";
cout<<"关键路径"<<endl;
for(int i=1;i<=k;i++){
if(ve[i]==vl[i]){
cout<<'v'<<i<<" ";
}
}
return 0;
}