基础实验6-2.6 最短工期 (25分)
Given the relations of all the activities of a project, you are supposed to find the earliest completion time of the project.
一个项目由若干个任务组成,任务之间有先后依赖顺序。项目经理需要设置一系列里程碑,在每个里程碑节点处检查任务的完成情况,并启动后续的任务。现给定一个项目中各个任务之间的关系,请你计算出这个项目的最早完工时间。
Input Specification:
Each input file contains one test case. Each case starts with a line containing two positive integers N (≤100), the number of activity check points (hence it is assumed that the check points are numbered from 0 to N−1), and M, the number of activities. Then M lines follow, each gives the description of an activity. For the i-th activity, three non-negative numbers are given: S[i], E[i], and L[i], where S[i] is the index of the starting check point, E[i] of the ending check point, and L[i] the lasting time of the activity. The numbers in a line are separated by a space.
首先第一行给出两个正整数:项目里程碑的数量 N(≤100)和任务总数 M。这里的里程碑从 0 到 N−1 编号。随后 M 行,每行给出一项任务的描述,格式为“任务起始里程碑 任务结束里程碑 工作时长”,三个数字均为非负整数,以空格分隔。
Output Specification:
For each test case, if the scheduling is possible, print in a line its earliest completion time; or simply output “Impossible”.
如果整个项目的安排是合理可行的,在一行中输出最早完工时间;否则输出"Impossible"。
Sample Input 1:
9 12
0 1 6
0 2 4
0 3 5
1 4 1
2 4 1
3 5 2
5 4 0
4 6 9
4 7 7
5 7 4
6 8 2
7 8 4
Sample Output 1:
18
Sample Input 2:
4 5
0 1 1
0 2 2
2 1 3
1 3 4
3 2 5
Sample Output 2:
Impossible
C语言实现:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
struct graph
{
int Ne;
int Nv;
int * * M;
};
typedef struct graph * Graph;
struct que
{
int front;
int rear;
int * s;
};
typedef struct que * Queue;
Queue CreateQ(int N);
void AddQ(Queue Q, int y);
int DeleteQ(Queue Q);
Graph CreateGraph(int N);
int main()
{
int N, M;
scanf("%d %d", &N, &M);
int i, j;
Graph G;
G = CreateGraph(N);
G->Ne = M;
int v1, v2, w;
for (i = 0; i < M; i++)
{
scanf("%d %d %d", &v1, &v2, &w);
G->M[v1][v2] = w;
}
int * Indegree;//记录各顶点入度
Indegree = (int *)malloc(N * sizeof(int));
for (i = 0; i < N; i++)
{
Indegree[i] = 0;
}
for (i = 0; i < N; i++)//初始化
{
for (j = 0; j < N; j++)
{
if (G->M[j][i] != -1)
{
Indegree[i]++;
}
}
}
int V = 0;
int * Earliest;//记录各顶点的最早完工时间
Earliest = (int *)malloc(N * sizeof(int));
Queue Q;
Q = CreateQ(N);
for (i = 0; i < N; i++)//初始化
{
Earliest[i] = -1;
}
for (i = 0; i < N; i++)
{
if (Indegree[i] == 0)//找起点
{
AddQ(Q, i); Earliest[i] = 0;
for (j = 0; j < N; j++)//删除图中起点的出边
{
if (G->M[i][j] != -1)
{
Indegree[j]--;
}
}
}
}
while (Q->front != Q->rear)
{
V = DeleteQ(Q);
for (i = 0; i < N; i++)
{
for (j = 0; j < N; j++)
{
if (G->M[V][j] != -1)//更新顶点V的所有邻接点的最短完工时间,各个顶点取其所有最短完工时间中的最大值
{
if (Earliest[j] < Earliest[V] + G->M[V][j])
{
Earliest[j] = Earliest[V] + G->M[V][j];
}
}
}
if (Indegree[i] == 0 && G->M[V][i] != -1)//入度=0的顶点放入队列中,并删除图中该顶点的出边
{
AddQ(Q, i);
for (j = 0; j < N; j++)
{
if (G->M[i][j] != -1 && Indegree[j] != 0)
{
Indegree[j]--;
}
}
}
}
}
for (i = 0; i < N; i++)//存在环路,则项目不合理
{
if (Earliest[i] == -1)
{
printf("Impossible");
break;
}
}
if (i == N)//项目合理,这里考虑到可能有多个终点,所以输出所有顶点的最短完工时间的最大值
{
int max = Earliest[0];
for (i = 1; i < N; i++)
{
if (Earliest[i] > max)
{
max = Earliest[i];
}
}
printf("%d", max);
}
return 0;
}
Graph CreateGraph(int N)
{
int i, j;
Graph G;
G = (Graph)malloc(sizeof(struct graph));
G->Ne = 0;
G->Nv = N;
G->M = (int * *)malloc(N * sizeof(int *));
for (i = 0; i < N; i++)
{
G->M[i] = (int *)malloc(N * sizeof(int));
}
for (i = 0; i < N; i++)
{
for (j = 0; j < N; j++)
{
G->M[i][j] = -1;
}
}
return G;
}
Queue CreateQ(int N)
{
Queue Q;
Q = (Queue)malloc(sizeof(struct que));
Q->front = Q->rear = -1;
Q->s = (int *)malloc(N * sizeof(int));
return Q;
}
void AddQ(Queue Q, int y)
{
Q->rear++;
Q->s[Q->rear] = y;
}
int DeleteQ(Queue Q)
{
Q->front++;
return Q->s[Q->front];
}