题目8:关键路径
问题描述
计算AOE-网中关键路径的长度。
输入格式
输入数据第一行是一个正整数,表示图中的顶点个数n(顶点将分别按0,1,…,n-1进行编号),顶点数不超过100,其中0为源点,n-1为汇点。之后的n行每行都包含n个整数,为AOE-网的邻接矩阵,其中0表示两个顶点间无直接可达的弧,大于0的整数表示活动持续的时间。
输出格式
输出AOE-网中关键路径的长度,如果网中有环,则输出“NO”。
样例输入
9
0 6 4 5 0 0 0 0 0
0 0 0 0 1 0 0 0 0
0 0 0 0 1 0 0 0 0
0 0 0 0 0 2 0 0 0
0 0 0 0 0 0 9 7 0
0 0 0 0 0 0 0 4 0
0 0 0 0 0 0 0 0 2
0 0 0 0 0 0 0 0 4
0 0 0 0 0 0 0 0 0
样例输出
18
输出说明:如果网中有环,则示例输出如下:
NO
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
int IsCirle(int arcs[100][100], int n);
int main()
{
int n;
int i, j;
int arcs[100][100];
scanf("%d", &n);
for (i = 0; i < n; i++)//输入邻接矩阵
{
for (j = 0; j < n; j++)
{
scanf("%d", &arcs[i][j]);
}
}
if (IsCirle(arcs, n) == 1)
{
printf("NO");
}
else
{
//求拓扑排序序列
//要用拓扑排序来计算事件最早发生时间
int base[100] = { 0 };//栈
int* top = base;
int t[100] = { 0 };//存储拓扑排序
int indegree[100] = { 0 };//记录入度
int k = 0;//作为下标
for (i = 0; i < n; i++)//初始化入度数组
{
for (j = 0; j < n; j++)
{
if (arcs[j][i] != 0)
indegree[i]++;
}
}
for (i = 0; i < n; i++)//将入度为零的结点入栈
{
if (indegree[i] == 0)
{
*top = i;
top++;
}
}
while (top != base)
{
int e = *(top - 1);
top--;
t[k] = e;//记录
k++;
for (i = 0; i < n; i++)//删除这个结点带来的出度
{
if (arcs[e][i] != 0)
{
indegree[i]--;
if (indegree[i] == 0)//将入度为零的结点入栈
{
*top = i;//入栈
top++;
}
}
}
}
int etv[100] = { 0 };//事件(结点)最早发生时间
//用拓扑排序的顺序来求 事件最早发生时间
for (i = 0; i < k; i++)
{
int e = t[i];
for (j = 0; j < n; j++)
{
if (arcs[e][j] != 0)//存在从这个结点到另一个结点可达
{
if (arcs[e][j] + etv[e] > etv[j])//事件发生的最早时间是 前一个结点最早时间加两结点间的活动时间 的最大值
{
etv[j] = arcs[e][j] + etv[e];
}
}
}
}
printf("%d", etv[n - 1]);
}
return 0;
}
int IsCirle(int arcs[100][100], int n)
{
int i, j, k;
int count = 0;
int indegree[100] = { 0 };
for (i = 0; i < n; i++) //记录每个结点的入度
{
for (j = 0; j < n; j++)
{
if (arcs[j][i] != 0)
indegree[i]++;
}
}
int base[100] = { 0 };
int* top = base;
for (i = 0; i < n; i++)//先将入度为零的结点入栈
{
if (indegree[i] == 0)
{
*top = i;
top++;
}
}
while (top != base)//栈不为空
{
int e = *(top - 1);
top--;
count++;
for (i = 0; i < n; i++)
{
if (arcs[e][i] != 0)//删除这个结点带来的出度
{
indegree[i]--;
if (indegree[i] == 0)
{
*top = i;
top++;
}
}
}
}
if (count < n)//有回路
return 1;
else
return 0;
}