1. 程式人生 > >PAT--How Long Does It Take (25)

PAT--How Long Does It Take (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.

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

典型的拓撲排序,可是很久沒刷過類似的題了。還是有必要好好研究研究。

重點就在於,拓撲排序過程中如何記錄cost,以及如果有多個重點最後輸出何值。

解決方法是,在要刪掉某個可以拿出來的節點時,修正這條節點(front)指向的節點(i)的cost值cost[i]=max(cost[i],cost[front]+info[front][i]);

最後輸出出度為零的節點中耗時最多的節點cost。其實單純輸出最大值也行。

#include<stdio.h>
#define num 100
#include<queue>
using namespace std;

//節點個數,邊數
int N,M;
//bool isin[num];
//入度,出度,每個節點需要花費時間,節點之間關係矩陣
int indgree[num];
int outdegree[num];
int cost[num];
int info[num][num];
//初始化,
void init(){
	int i,j;
	for(i=0;i<num;i++){
		for(j=0;j<num;j++){
			info[i][j]=-1;
		}
		indgree[i]=0;
		outdegree[i]=0;
		cost[i]=0;
	}
}
//求最大值
int max(int x,int y){
	return x>y?x:y;
}
//主方法
int solve(){
	int n=0;
	int i,front;
	queue<int> Q;
	for(i=0;i<N;i++){
		if(indgree[i]==0){
			//入度為0的節點入隊。
			Q.push(i);
			//讓其不再是0,否則會影響後面的入隊
			indgree[i]--;
		}
	}
	//Q不空則迴圈,
	while(!Q.empty()){
		front=Q.front();
		Q.pop();
		n++;//記錄現在有多少節點出隊
		//出隊的都是可以抹掉的節點
		for(i=0;i<N;i++){
			if(info[front][i]>=0){//如果要抹掉的節點與某個節點有一條有向邊,
				//該邊入度減一,計算該邊的cost
				indgree[i]--;
				cost[i]=max(cost[i],cost[front]+info[front][i]);
			}
		}
		//重新尋找需要入隊的
		for(i=0;i<N;i++){
			if(indgree[i]==0){
				Q.push(i);
				indgree[i]--;
			}
		}
	}
	//如果刪掉N個邊說明沒有環,注意cost[front]不是最終結果
	if(n==N)return cost[front];
	//否則
	return -1;
}

int main(){
	int file=0;
	FILE* fp;
	init();
	int i,temp1,temp2,temp3;
	if(file){
		
		fp=fopen("1.txt","r");
		if(fp==NULL){
			puts("ERROR!");
		}
		fscanf(fp,"%d%d",&N,&M);
		for(i=0;i<M;i++){
			fscanf(fp,"%d%d%d",&temp1,&temp2,&temp3);
			info[temp1][temp2]=temp3;
			indgree[temp2]++;
			outdegree[temp1]++;
			//printf("%d,%d,%d\n",temp1,temp2,info[temp1][temp2]);
		}
	}
	else{
		scanf("%d%d",&N,&M);
		for(i=0;i<M;i++){
			scanf("%d%d%d",&temp1,&temp2,&temp3);
			info[temp1][temp2]=temp3;
			indgree[temp2]++;
			outdegree[temp1]++;
		}
	}
	int res;
	res=solve();
	if(res==-1){
		puts("Impossible");
	}
	else{
		for(i=0;i<N;i++){
			if(outdegree[i]==0)
				//可能有多個終點,需要找到耗時最多的那個
				res=max(cost[i],res);
		}
		printf("%d\n",res);
	}

	return 0;
}