Clasificación topológica AOE + encontrar el período de construcción más corto + encontrar el tiempo de maniobra de cada lado + obtener la ruta crítica 08-Figura 9 actividades críticas (30 puntos)

08-Figura 9 Actividades clave (30 puntos)

Suponga que un proyecto de ingeniería se compone de un conjunto de subtareas, algunas de las cuales pueden ejecutarse en paralelo, y algunas deben completarse después de completar otras subtareas. La "programación de tareas" incluye un conjunto de subtareas y un conjunto de subtareas en las que se puede ejecutar cada subtarea.

Por ejemplo, completar todos los cursos y el diseño de graduación de una especialización puede considerarse como un proyecto para ser completado por un estudiante universitario, y cada curso puede considerarse como una subtarea. Algunos cursos se pueden ofrecer al mismo tiempo, como la programación en inglés y C, no tienen que estar sujetos a restricciones; algunos cursos no se pueden ofrecer al mismo tiempo, ya que tienen dependencias sucesivas, como la programación en C y la estructura de datos de dos cursos, Lo primero debe estudiarse primero.

Sin embargo, debe tenerse en cuenta que, para un grupo de subtareas, la programación no arbitraria de tareas es una solución factible. Por ejemplo, hay una "subtarea A depende de la subtarea B, la subtarea B depende de la subtarea C y la subtarea C depende de la subtarea A" en el plan, entonces ninguna de estas tres tareas puede ejecutarse primero, lo cual es inviable Esquema

En el problema de programación de tareas, si también se da el tiempo requerido para completar cada subtarea, podemos calcular el tiempo mínimo requerido para completar todo el proyecto. Entre estas subtareas, algunas tareas no afectarán el cronograma general, incluso si se retrasan por unos días, sin embargo, algunas tareas deben completarse a tiempo, de lo contrario la duración de todo el proyecto se retrasará. Esta tarea se llama "actividad crítica".

Escriba un programa para determinar si la programación de tareas de un proyecto de ingeniería determinado es factible; si el esquema de programación es factible, calcule el tiempo mínimo requerido para completar todo el proyecto de ingeniería y generar todas las actividades clave.

Formato de entrada:
ingrese la primera línea para dar dos enteros positivos N (≤100) y M, donde N es el punto de unión de la tarea (es decir, el nodo que conecta dos subtareas que dependen entre sí, por ejemplo: si la tarea 2 debe completarse después de la tarea 1 Antes de comenzar, debe haber un punto de unión entre las dos tareas). Los puntos de unión están numerados por 1 N, M es el número de subtareas y luego están numerados 1 M. En las siguientes líneas M, cada línea da 3 enteros positivos, que son el número de puntos de unión involucrados en el inicio y la finalización de la tarea y el tiempo requerido para la tarea. Los enteros están separados por espacios.

Formato de salida:
si la programación de tareas no es factible, salida 0; de lo contrario, la línea 1 muestra el tiempo requerido para completar todo el proyecto, la línea 2 comienza a generar todas las actividades clave, cada actividad clave ocupa una línea, de acuerdo con el formato "V-> W" Salida, donde V y W son los puntos de unión involucrados en el inicio y la finalización de la tarea. La regla de secuencia para la salida de actividades clave es: cuanto más pequeño es el número de punto de unión al comienzo de la tarea, y el orden de la tarea se invierte cuando el número de punto de partida es el mismo.

Entrada de muestra:

7 8
1 2 4
1 3 3
2 4 5
3 4 3
4 5 1
4 6 6
5 7 5
6 7 2

Salida de muestra:

17
1->2
2->4
4->6
6->7

El problema integral de la clasificación topológica AOE
puede encontrar la duración total y el tiempo de maniobra de cada tarea.

Cada lado representa un proyecto ;
cada nodo representa un punto de transferencia de tareas ;
1. Encuentre la duración más corta de cada lado;
2. Invierta, encuentre el tiempo de inicio más temprano de cada punto;
3. Reste los dos para obtener la maniobra de cada tarea Tiempo, la tarea de generar el tiempo de maniobra 0 en secuencia es el camino del punto clave;

A [] [] almacena el tiempo requerido para cada tarea;
D [] [] almacena el tiempo de maniobra de cada tarea;
Earliest [] almacena el tiempo de inicio más temprano de
cada nodo ; Latest [] almacena el tiempo máximo de cada nodo Hora de inicio tardía;
la hora de inicio más temprana del nodo actual + el tiempo requerido para la tarea = la última hora de inicio del siguiente nodo, lo que indica que el tiempo de maniobra de la tarea es 0, que es la tarea clave;

Función 1.main

#include<iostream>
#include<queue>
using namespace std;

#define MAX 105
#define INFINITY 65535

int N,M,A[MAX][MAX],ECT,EarliestTime[MAX]={0},LatestTime[MAX],D[MAX][MAX],idx;

Guarde el tiempo requerido por la tarea en A [] [], inicialice el tiempo de maniobra de cada tarea para inf;
TopSort_Earliest (), calcule el tiempo de finalización más temprano de cada tarea;
y cuente el número de tareas para determinar si el gráfico está conectado;
TopSort_Latest (), Calcule el último tiempo de inicio de cada tarea; la función
PrintKeyRoute () genera tareas clave una por una;

int main(){
	int a,b;
	scanf("%d %d",&N,&M);
	
	//初始化拓扑图A以及各边机动值 
	for(int i=0;i<N;i++)
		for(int j=0;j<N;j++)
			D[i][j]=A[i][j]=INFINITY;
			
	//得到拓扑图A 
	for(int i=0;i<M;i++)
	{
		scanf("%d %d",&a,&b);
		scanf("%d",&A[--a][--b]); //编号从1开始,保存从0保存 
	}
	if(!TopSort_Earliest())
		printf("0\n");
	else{
		printf("%d\n",ECT);
		TopSort_Latest();
		PrintKeyRoute();
	}
	
} 

2. Función getMax
Obtenga el valor máximo en Anterior y guarde el subíndice;
la hora de finalización más temprana del punto final es el valor máximo de la hora de finalización más temprana de cada punto;
encuentre el punto final y guarde el valor máximo para la primera salida;

int getMax(int arr[])      //得到列表中最大的元素 
{
	int max=0;
	for (int i=0;i<N;i++)
		if(max<arr[i])
			{
				max=arr[i];     //找到最大值的值 
				idx=i;       //找到最大值的编号 
			}
	return max;	
}

3. Función más temprana
Calcula el grado del gráfico A dirigido;
coloca el nodo con el grado 0 en el equipo;
ingresa al bucle: el
equipo sale del equipo, registra el número de tareas cnt ++,
atraviesa el nodo adyacente de finalización de la tarea después del nodo de la cabeza del montón Si el nodo actual más el tiempo de tarea es mayor que el tiempo de inicio del siguiente nodo, actualice el tiempo de inicio del siguiente nodo a un valor grande
;

int TopSort_Earliest(){
	int V,cnt = 0, Indegree[MAX] = {0};
	queue<int> q; 
	//计算各节点入度
	for(int i=0;i<N;i++)
		for(int j=0;j<N;j++)
			if(A[i][j]!=INFINITY)
				Indegree[j]++;
	
	//找到入度为0的入队
	for(int i=0;i<N;i++)
		if(Indegree[i]==0)
			q.push(i);
			
	while(!q.empty()){
		V = q.front();     //得到队头元素 
		q.pop();
		cnt++;       //记录结点数
		for(int j=0;j<N;j++)
			if(A[V][j]!=INFINITY){    //找到V后面的边 
				if(EarliestTime[V]+A[V][j]>EarliestTime[j]){
			//取最大的完成时间 
					EarliestTime[j]=EarliestTime[V]+A[V][j];
				}
				if(--Indegree[j]==0)
				//若该相邻边入度为0,入队 
					q.push(j); 
			}	
	}
	ECT=getMax(EarliestTime);       //找到最大元素——即最少总时间
	if(cnt!=N) return 0;   //代表图不连通 
	else return 1;        
}
// Earlist已算出每个活动的最晚时间

Finalmente, getmax obtiene el índice y el valor máximo del punto final y usa cnt para determinar si el gráfico está conectado.

4.Función
última Calcular el último tiempo de inicio de cada nodo;
retroceder desde el vértice final idx;
calcular el grado de salida de cada nodo, poner el grado de salida en 0;
inicializar el tiempo de finalización más temprano del vértice final;
iniciar el ciclo :
uno a uno fuera del equipo, a través de cada nodo predecesor del nodo, un nodo antes de la hora de tomar la hora de inicio del nodo actual menos el tiempo mínimo que se necesita antes de una tarea que comienza tan pronto como sea posible;
mosto Con <=, solo <, solo se puede calcular una ruta crítica y <= puede calcular todas las rutas críticas (la causa del error).
Además, se requiere el tiempo de la computadora de la matriz D, es decir, el tiempo de inicio del nodo anterior + el tiempo de la tarea es el correcto. = El tiempo de inicio del nodo actual, entonces la tarea no tiene tiempo de maniobra;
el nodo con un grado de 0 se pondrá en cola después de eliminar este punto;

void TopSort_Latest(){
	int V,Outdegree[MAX] = {0};  //出度初始化为0 
	queue<int> q;
				//计算各节点的出度
	for(int i=0; i<N; i++)
		for(int j=0;j<N;j++)
			if(A[i][j]!=INFINITY)
				Outdegree[i]++;      //计算出度 
	//出度为0的入队
	for(int i=0;i<N;i++)
		if(Outdegree[i]==0)
			q.push(i);

	//初始化latesttime
	for(int i=0;i<N;i++)
		LatestTime[i]=INFINITY;
	
	LatestTime[idx]=ECT; //idx为最后一个活动的编号;ECT为该点完成的时间
	//从后往前推
	while(!q.empty())
	{
		V=q.front();
		q.pop();
		//cnt++  以得出图是否联通,cnt无用
		for(int j=0;j<N;j++)
			if(A[j][V]!=INFINITY){    //找到V前面的结点 
				if(LatestTime[V]-A[j][V]<=LatestTime[j]){
					//找到最晚开始的时间,即前面的点最早需要开始的时间 
//必须用<=,只<的话只能算一条关键路径,<=才能算出所有的关键路径(错误原因)
					LatestTime[j]=LatestTime[V]-A[j][V];
					
					D[j][V]=LatestTime[V]-EarliestTime[j]-A[j][V];
			//D为机动时间:即V的最晚开始时间-(j的最早开始时间+j到V所花的时间)
			//j的最早开始时间+j到v所花的时间若等于v的最晚开始时间,则说明
			//从j到v没有机动时间,即j-v是一条可输出的路径 
				} 
				if(--Outdegree[j]==0)
					q.push(j);
			} 
	 } 
} 

5. Función de salida

void PrintKeyRoute()
{
	for(int i=0;i<N;i++)    //任务开始的交接点编号小者优先 
		for(int j=N-1;j>=0;j--)    //起点编号相同时,与输入时任务的顺序相反。
			if(D[i][j]==0)
				printf("%d->%d\n",i+1,j+1); 
}

Resumen
ruta crítica: hay varias rutas de misión con un tiempo de maniobra de 0; para
encontrar una ruta crítica, primero debe encontrar la hora de finalización más temprana y luego la última hora de inicio; la
hora de finalización del punto actual + el tiempo de tarea iniciado en este punto = siguiente El tiempo de inicio de la tarea indica que el tiempo de maniobra de la tarea es 0, que se puede mostrar como punto clave;

Publicados 105 artículos originales · ganado elogios 6 · vistas 4949

Supongo que te gusta

Origin blog.csdn.net/BLUEsang/article/details/105522686
Recomendado
Clasificación