PTA_22_08_图8 _How Long Does It take

PTA_22_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.

考虑到一个项目所有活动的关系,你应该找到项目最早的完成时间。

输入格式

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),活动检查点的数量(因此假设检查点的编号从0到N−1) ,和M,活动的数量。接下来是M行,每行给出一个活动的描述。对于第i个活动,给出了三个非负数:S[i]、E[i]和L[i],其中S[i]是开始检查点的索引,E[i]是结束检查点,L[i]是活动的持续时间。一行中的数字用空格分隔。

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

**************
4 5
0 1 1
0 2 2
2 1 3
1 3 4
3 2 5

输出样式

For each test case, if the scheduling is possible, print in a line its earliest completion time; or simply output “Impossible”.

对于每个测试用例,如果调度是可能的,则在一行中打印其最早完成时间;或者干脆输出“不可能”。

18
*************
Impossible

算法设计

根据陈越姥姥所说,本题是要用拓扑排序的思路进行求解

那么首先我们需要了解拓扑结构到底是什么,拓扑结构的算法很简单就是从AOV网中选择一个入度为0的顶点输出,然后删去此顶点,并删除以此顶点为尾的弧,继续重复此步骤,直到输出全部顶点或则AOV网中不存在入度为0的顶点为止。

AOV网的概念则是,在一个表示工程的有向图中,用顶点表示活动,用弧表示活动之间的优先关系,这样的有向图为顶点表示活动的网,我们称为AOV网。

对于拓扑结构往往采用邻接表的形式。

更完全的说,本题应该采用拓扑排序+关键路径两者相结合的算法

代码实现

#include<stdio.h>
#include<iostream>
#include<queue>

using namespace std;
#define MAXSIZE 100
#define INFINITY 65535

struct Node
{
	int N;
	int M;
	int A[MAXSIZE][MAXSIZE];
};
typedef struct Node* Pgraph;

int collect_time;//统计时间


void Creategraph(Pgraph graph)
{
	int i, j;
	int tmpstart, tmpend, tmptime;
	cin >> graph->N >> graph->M;
	//初始化边集
	for ( i = 0; i < graph->N; i++)
	{
		for (j = 0; j < graph->N; j++)
		{
			graph->A[i][j] = INFINITY;
		}
	}
	//将边集输入
	for (i = 0; i < graph->M; i++)
	{
		cin >> tmpstart >> tmpend >> tmptime;
		//因为是有相图
		graph->A[tmpstart][tmpend] = tmptime;
	}
}


int getmax(int arr[],Pgraph graph)
{
	int max = 0;
	for (int i = 0; i < graph->N; i++)
	{
		if (arr[i] > max)
		{
			max = arr[i];
		}
	}
	return max;
}


int topsort(Pgraph graph)
{
	int v,i,j;
	int cnt=0;//计算出队列元素的个数
	int indrgree[MAXSIZE] = { 0 };//记录各点的入度
	int EarliestTime[MAXSIZE] = { 0 };//记录最早完成的时间
	queue<int>q;
	//计算各结点的入度
	for ( i = 0; i < graph->N; i++)
	{
		for (j = 0; j < graph->N; j++)
		{
			if (graph->A[i][j] != INFINITY)
			{
				indrgree[j]++;//对于有向边<i,j>累计记录终点为j的度
			}
		}
	}

	//入度为0的i入队
	for (int i = 0; i < graph->N; i++)
	{
		if (indrgree[i] == 0)
			q.push(i);
	}

	while (!q.empty())//当队列不空时
	{
		v = q.front();//v等于要出队列的元素
		q.pop();
		cnt++;
		for (j = 0; j < graph->N; j++)
		{
			if(graph->A[v][j]!=INFINITY)//如果<v,j>存在有向边
			{
				if (EarliestTime[v] + graph->A[v][j] > EarliestTime[j])
				{//如果v的最早完成时间+j所需时间>j的最早完成时间
					EarliestTime[j] = EarliestTime[v] + graph->A[v][j];
					//由关键路径的算法定义得出的
				}
				if (--indrgree[j] == 0)//去掉v后,j的入度如果为0,这个--是对每一个j都有效
				{
					q.push(j);
				}
			}
		}
	}
	
	collect_time = getmax(EarliestTime, graph);
	if (cnt != graph->N)
	{
		cout << "Impoosible";
		return 0;
	}
	else
	{
		cout << collect_time;
	}
}

int main()
{
	Pgraph graph;
	graph = (Pgraph)malloc(sizeof(struct Node));
	Creategraph(graph);
	topsort(graph);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值