//要求按顺序输入
#include<stdio.h>
#include<string.h>
int n;
int a[100][100];//每个点的直接后继
int b[100][100];//每个点的直接前驱
int ea[10000];//某个边的起点
int eb[10000];//某个边的终点
int Ve[100];//事件的最早发生时间
int Vl[100];//事件的最迟发生时间
int early[10000];//活动的最早开始时间
int late[10000];//活动的最迟发生时间
int le[10000];//活动余量
bool guanjian[10000];//关键路径
void dfs(int p)
{
if (p==n)
return;
for (int i=p+1;i<=n;i++)
{
int temp;
if (a[p][i]!=-1)
{
temp=Ve[p]+a[p][i];
if (temp>Ve[i])
{
Ve[i]=temp;
}
dfs(i);
}
}
}
void dfs2(int p)
{
if (p==1)
return;
for (int i=p;i>=1;i--)
{
int temp;
if (b[p][i]!=-1)
{
temp=Vl[p]-b[p][i];
if (temp<Vl[i])
{
Vl[i]=temp;
}
dfs2(i);
}
}
}
int main()
{
scanf("%d",&n);
int s,e,p;
memset(a,-1,sizeof(a));
memset(b,-1,sizeof(b));
memset(ea,-1,sizeof(ea));
memset(eb,-1,sizeof(eb));
memset(guanjian,0,sizeof(guanjian));
//将所有的有向边写入矩阵
int m=0;
while (scanf("%d%d%d",&s,&e,&p))
{
m++;
if (s==0)
break;
ea[m]=s;
eb[m]=e;
a[s][e]=p;
b[e][s]=p;//虽然只有一条边,但是我们可以这样来确保找到直接前驱
}
m--;
//求取每个顶点的Ve和Vl
memset(Ve,0,sizeof(Ve));
memset(Vl,0,sizeof(Ve));
int start=1;
dfs(1);
printf("Ve:\n");
for (int i=1;i<=n;i++)
{
Vl[i]=9999999;
printf("%d ",Ve[i]);
}
Vl[n]=Ve[n];
printf("\n");
dfs2(n);
printf("Vl:\n");
for (int i=1;i<=n;i++)
{
printf("%d ",Vl[i]);
}
printf("\n");
for (int i=1;i<=m;i++)
{
early[i]=Ve[ea[i]];
late[i]=Vl[eb[i]]-a[ea[i]][eb[i]];
le[i]=late[i]-early[i];
}
printf("edge e l l-e\n");
for (int i=1;i<=m;i++)
{
printf("%3d %3d %3d %3d\n",i,early[i],late[i],le[i]);
}
printf("所以关键路径是:\n");
for (int i=1;i<=m;i++)
{
if (!le[i])
{
printf("a%d ",i);
}
}
printf("\n");
}
给出两组输入,分别对应下面的两幅图
输入一:
9
1 2 6
1 3 4
1 4 5
2 5 1
3 5 1
4 6 2
5 7 9
5 8 7
6 8 4
7 9 2
8 9 4
0 0 0
输入二:
13
1 2 1
1 3 6
1 4 3
1 5 4
1 6 3
1 7 1
2 9 6
3 9 2
4 9 7
4 11 6
4 12 8
5 8 5
5 12 11
6 8 10
6 13 21
7 8 6
8 9 4
8 10 9
8 11 4
9 12 8
10 11 9
11 12 3
11 13 12
12 13 10
0 0 0
图一
图二