版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/grooowing/article/details/45248941
题目太长了,先略去。
还是拓扑排序,建议先了解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){//如果要抹掉的节点与某个节点有一条有向边,
//该边入度减一,计算该边的cost
indgree[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){//如果某个节点与要抹掉的节点有一条有向边,
//该边出度减一,计算该边的last
outdegree[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;
}