08-图8 How Long Does It Take

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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值