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.
Output Specification:
For each test case, if the scheduling is possible, print in a line its earliest completion time; or simply output “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
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#define MaxVertexNum 100 /* 最大顶点数设为100 */
typedef int Vertex; /* 用顶点下标表示顶点,为整型 */
typedef int WeightType; /* 边的权值设为整型 */
int Earliest[MaxVertexNum];
/* 边的定义 */
typedef struct ENode *PtrToENode;
struct ENode
{
Vertex V1, V2; /* 有向边<V1, V2> */
WeightType Weight; /* 权重 */
};
typedef PtrToENode Edge;
/* 邻接点的定义 */
typedef struct AdjVNode *PtrToAdjVNode;
struct AdjVNode
{
Vertex AdjV; /* 邻接点下标 */
WeightType Weight; /* 边权重 */
PtrToAdjVNode Next; /* 指向下一个邻接点的指针 */
};
/* 顶点表头结点的定义 */
typedef struct Vnode
{
PtrToAdjVNode FirstEdge;/* 边表头指针 */
} AdjList[MaxVertexNum]; /* AdjList是邻接表类型 */
/* 图结点的定义 */
typedef struct GNode *PtrToGNode;
struct GNode
{
int Nv; /* 顶点数 */
int Ne; /* 边数 */
AdjList G; /* 邻接表 */
};
typedef PtrToGNode LGraph; /* 以邻接表方式存储的图类型 */
typedef struct QNode *Queue;
struct QNode
{
int Data[MaxVertexNum];
int rear;
int front;
};
LGraph BuildGraph();
bool TopSort(LGraph Graph);
int main()
{
Vertex E;//流程结束点
LGraph Graph = BuildGraph();
for (Vertex V=0; V<Graph->Nv; V++)
if(!Graph->G[V].FirstEdge)
E = V;
if(TopSort(Graph))printf("%d", Earliest[E]);
else printf("Impossible");
return 0;
}
LGraph CreateGraph( int VertexNum )
{ /* 初始化一个有VertexNum个顶点但没有边的图 */
Vertex V;
LGraph Graph;
Graph = (LGraph)malloc( sizeof(struct GNode) ); /* 建立图 */
Graph->Nv = VertexNum;
Graph->Ne = 0;
/* 初始化邻接表头指针 */
/* 注意:这里默认顶点编号从0开始,到(Graph->Nv - 1) */
for (V=0; V<Graph->Nv; V++)
Graph->G[V].FirstEdge = NULL;
return Graph;
}
void InsertEdge( LGraph Graph, Edge E )
{
PtrToAdjVNode NewNode;
/* 插入边 <V1, V2> */
/* 为V2建立新的邻接点 */
NewNode = (PtrToAdjVNode)malloc(sizeof(struct AdjVNode));
NewNode->AdjV = E->V2;
NewNode->Weight = E->Weight;
/* 将V2插入V1的表头 */
NewNode->Next = Graph->G[E->V1].FirstEdge;
Graph->G[E->V1].FirstEdge = NewNode;
}
LGraph BuildGraph()
{
LGraph Graph;
Edge E;
Vertex V;
int Nv, i;
scanf("%d", &Nv); /* 读入顶点个数 */
Graph = CreateGraph(Nv); /* 初始化有Nv个顶点但没有边的图 */
scanf("%d", &(Graph->Ne)); /* 读入边数 */
if ( Graph->Ne != 0 )
{ /* 如果有边 */
E = (Edge)malloc( sizeof(struct ENode) ); /* 建立边结点 */
/* 读入边,格式为"起点 终点 权重",插入邻接矩阵 */
for (i=0; i<Graph->Ne; i++)
{
scanf("%d %d %d", &E->V1, &E->V2, &E->Weight);
InsertEdge( Graph, E );
}
}
return Graph;
}
Queue CreateQueue()
{
Queue Q = (Queue)malloc(sizeof(struct QNode));
Q->front = Q->rear = 0;
return Q;
}
void AddQ(Queue Q, int R)
{
Q->rear = (Q->rear + 1) % MaxVertexNum;
Q->Data[Q->rear] = R;
}
int DeleteQ(Queue Q)
{
Q->front = (Q->front + 1) % MaxVertexNum;
int R = Q->Data[Q->front];
return R;
}
bool IsEmpty(Queue Q)
{
return (Q->front == Q->rear);
}
/* 邻接表存储 - 拓扑排序算法 */
bool TopSort(LGraph Graph)
{ /* 对Graph进行拓扑排序*/
int Indegree[MaxVertexNum], cnt, t[MaxVertexNum];
Vertex V;
PtrToAdjVNode W;
Queue Q = CreateQueue( Graph->Nv );
/* 初始化Indegree[] */
for (V=0; V<Graph->Nv; V++)
{
Indegree[V] = 0;
Earliest[V] = 0;
t[V] = 0;
}
/* 遍历图,得到Indegree[] */
for (V=0; V<Graph->Nv; V++)
for (W=Graph->G[V].FirstEdge; W; W=W->Next)
Indegree[W->AdjV]++; /* 对有向边<V, W->AdjV>累计终点的入度 */
/* 将所有入度为0的顶点入列 */
for (V=0; V<Graph->Nv; V++)
if ( Indegree[V]==0 )
AddQ(Q, V);
/* 下面进入拓扑排序 */
cnt = 0;
while( !IsEmpty(Q) )
{
V = DeleteQ(Q); /* 弹出一个入度为0的顶点 */
cnt++;
/* 对V的每个邻接点W->AdjV */
for ( W=Graph->G[V].FirstEdge; W; W=W->Next )
{
Indegree[W->AdjV]--;
if (Indegree[W->AdjV] == 0 && !t[W->AdjV])/* 若删除V使得W->AdjV入度为0 */
{
AddQ(Q, W->AdjV); /* 则该顶点入列 */
Earliest[W->AdjV] = Earliest[V] + W->Weight;
}
else
{
t[W->AdjV] = 1;//标记入度大于1的点
if(Indegree[W->AdjV] == 0)
AddQ(Q, W->AdjV);
if(Earliest[V] + W->Weight > Earliest[W->AdjV])
Earliest[W->AdjV] = Earliest[V] + W->Weight;
}
}
}
if ( cnt != Graph->Nv )
return false; /* 说明图中有回路, 返回不成功标志 */
else
return true;
}