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;
}

	




  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值