PAT--关键活动(30)

来源:互联网 发布:手机画板软件那个好 编辑:程序博客网 时间:2024/05/22 10:43

题目太长了,先略去。

还是拓扑排序,建议先了解http://blog.csdn.net/grooowing/article/details/45201267

这题主要就是

1,求出活动最早完成时间early[i],

early[i]=max{early[i]+<i,j>};顺推。

2,求出活动在不拖延整体工期是最晚完成时间last[i];从后向前推:

last[i]=min{last[j]-<i,j>}//注意是j

3,对于i->j,如果有有向边,那么灵活时间就是last[j]-early[i]-<i,j>,如果为0,则为关键路径。


详见代码,其实

http://blog.csdn.net/grooowing/article/details/45201267

这个如果明白了,这题就不难啦。注意我的“呵呵呵呵呵”,在顺推的时候,入度为0的节点,early初始值应该是0,但逆推的时候,对于出度为0的节点,last的初值,应该是最大的工期,就是第一个输出的那个值。


#include<stdio.h>#define num 100#include<queue>#include<algorithm>using namespace std;//节点个数,边数int N,M;//bool isin[num];//入度,出度,每个节点需要花费时间,节点之间关系矩阵int indgree[num];int outdegree[num];int early[num];int last[num];int info[num][num];//初始化,int hehehe;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;last[i]=100000;early[i]=0;}}//求最大值int max(int x,int y){return x>y?x:y;}int min(int x,int y){return x<y?x:y;}typedef struct {int i,j;int xuhao;}Node;Node node[num][num];bool cmp(Node a,Node b){return a.xuhao>b.xuhao;}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){//如果要抹掉的节点与某个节点有一条有向边,//该边入度减一,计算该边的costindgree[i]--;early[i]=max(early[i],early[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 early[front];//否则return -1;}//从后向前void solve2(){queue<int> Q;int i,front;for(i=0;i<N;i++){if(outdegree[i]==0){//出度为0的节点入队。Q.push(i);//初始化//last[i]=early[i];//呵呵呵呵呵呵呵呵呵last[i]=hehehe;//让其不再是0,否则会影响后面的入队outdegree[i]--;}}while(!Q.empty()){front=Q.front();Q.pop();//出队的都是可以抹掉的节点for(i=0;i<N;i++){if(info[i][front]>=0){//如果某个节点与要抹掉的节点有一条有向边,//该边出度减一,计算该边的lastoutdegree[i]--;last[i]=min(last[i],last[front]-info[i][front]);}}//重新寻找需要入队的for(i=0;i<N;i++){if(outdegree[i]==0){Q.push(i);outdegree[i]--;}}}}int main(){int file=0;FILE* fp;init();int i,temp1,temp2,temp3;if(file){fp=fopen("3.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-1][temp2-1]=temp3;indgree[temp2-1]++;outdegree[temp1-1]++;node[temp1-1][temp2-1].xuhao=i;//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);//注意序号从0开始info[temp1-1][temp2-1]=temp3;indgree[temp2-1]++;outdegree[temp1-1]++;//排序用node[temp1-1][temp2-1].xuhao=i;}}int res=solve();if(res==-1){puts("0");return 0;}else{for(i=0;i<N;i++){//可能有多个终点,需要找到耗时最多的那个res=max(early[i],res);//printf("%d,",early[i]);}printf("%d\n",res);hehehe=res;solve2();int j;Node nn[num];int s=0;for(i=0;i<N;i++){s=0;for(j=0;j<N;j++){if(info[i][j]>=0){if(last[j]-early[i]-info[i][j]==0){//printf("%d->%d\n",i+1,j+1);nn[s].i=i;nn[s].j=j;nn[s++].xuhao=node[i][j].xuhao;}}}//按输入相反次序排序sort(nn,nn+s,cmp);for(j=0;j<s;j++){printf("%d->%d\n",nn[j].i+1,nn[j].j+1);}}}return 0;}


0 0