//时间复杂度(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;
}
用Topo序列求关键路径
最新推荐文章于 2022-11-18 20:03:02 发布