7-3 最短工期(20 分) 一个项目由若干个任务组成,任务之间有先后依赖顺序。项目经理需要设置一系列里程碑,在每个里程碑节点处检查任务的完成情况,并启动后续的任务。现给定一个项目中各个任务之间的关系

#include<stdio.h>  
#include<string.h>  
#include<stdlib.h>  
#define MaxVertexNum 100   /* 最大定点数设为100 */   
typedef int Vertex;        /* 用顶点下标表示顶点,为整形 */   
typedef int WeightType;    /* 边的权值设为整形 */   
typedef char DataType;     /* 顶点储存的数据类型设为字符型 */   
int time[MaxVertexNum]={0};  
  
/* 队列的相关操作 */   
/* 队列的顺序储存实现结构定义 */   
typedef int ElementType;  
typedef int Position;  
typedef struct QNode *PtrToQNode;  
struct QNode{  
    ElementType *Data;    /* 储存元素的数组 */   
    Position Front, Rear; /* 队列的头尾指针 */   
    int MaxSize;          /* 队列的最大容量 */   
};  
typedef PtrToQNode Queue;  
/* 队列的创建 */  
Queue CreatQueue(int MaxSize)  
{  
    Queue Q = (Queue)malloc(sizeof(struct QNode));  
    Q->Data = (ElementType *)malloc(MaxSize*sizeof(ElementType));  
    Q->Front = Q->Rear=0;  
    Q->MaxSize = MaxSize;  
      
    return Q;  
}  
int IsFull(Queue Q)  
{  
    if((Q->Rear+1)%Q->MaxSize==Q->Front)  
        return 1;  
    else  
        return 0;  
}  
void AddQ(Queue Q, ElementType X)  /* 入队列 */   
{  
    if(IsFull(Q)){  
        printf("队列满");  
    }  
    else{  
        Q->Rear = (Q->Rear+1)%Q->MaxSize;  
        Q->Data[Q->Rear] = X;  
    }  
}  
int IsEmpty(Queue Q)  /* 判断队列是否为空 */   
{  
    if(Q->Front==Q->Rear)  
        return 1;  
    else  
        return 0;  
}  
ElementType DeleteQ(Queue Q)  /* 出队列 */   
{  
    if(IsEmpty(Q)) {  
        printf("队列空");  
    }  
    else  {  
        Q->Front = (Q->Front+1)%Q->MaxSize;  
        return Q->Data[Q->Front];  
    }  
}   
  
  
/* 边的定义 */  
typedef struct ENode *PtrToENode;  
struct ENode{  
    Vertex V1, V2;      /* 有向边<V1, V2> */   
    WeightType Weight;  /* 权重 */   
};  
typedef PtrToENode Edge;  
  
/* 邻结点的定义 */   
typedef struct AdjVNode *PtrToAdjVNode;  
struct AdjVNode{  
    Vertex AdjV;    /* 邻接点下标 */  
    WeightType Weight;  /* 边权重 */   
    PtrToAdjVNode Next;  
};  
  
/* 顶点表头节点的定义 */   
typedef struct Vnode{  
    PtrToAdjVNode FirstEdge; /* 边表头指针 */    
    //DataType Data;  
}AdjList[MaxVertexNum];  /* AdjList 是邻接表的类型 */   
  
/* 图节点的定义 */  
typedef struct GNode *ProToGNode;  
struct GNode{  
    int Nv;  /* 顶点数 */  
    int Ne;  /* 边数 */  
    AdjList G;  /* 邻接表 */   
};  
typedef ProToGNode LGraph;  
  
int TopOrder[MaxVertexNum];  
LGraph CreateGraph(int VertexNum) /* 初始化一个有N个顶点但是没有边的图  */   
{   
    Vertex V;  
    LGraph Graph;  
      
    Graph=(LGraph)malloc(sizeof(struct GNode));  /* 建立图 */  
    Graph->Nv=VertexNum;  
    Graph->Ne=0;  
    /* 初始化邻接表头指针 */   
    for( V = 0; V < Graph->Nv; V++)  
        Graph->G[V].FirstEdge=NULL;   
      
    return Graph;  
}  
void InsertEdge(LGraph Graph, Edge E)   //插入边   
{  
    PtrToAdjVNode NewNode;  
    /*插入边 <v1, v2>*/  
    /* 为V2建立新的邻接点 */  
    NewNode = (PtrToAdjVNode)malloc(sizeof(struct AdjVNode));  
    NewNode->AdjV = E->V2;  
    NewNode->Weight = E->Weight;   
    /* 将V2插入V1的表头 */  
    NewNode->Next=Graph->G[E->V1].FirstEdge;  
    Graph->G[E->V1].FirstEdge=NewNode;  
    /* 若是无向图还要插入边 */  
    /*为V1建立新的邻接点 */  
    //省略这一步   
}  
LGraph BuildGraph()  
{  
    LGraph Graph;  
    Edge E;  
    Vertex V;  
    int Nv, i;  
    scanf("%d", &Nv);  /* 读入顶点数 */   
    Graph = CreateGraph(Nv); /* 初始化一个有Nv个顶点但是没有边的图  */   
      
    scanf("%d", &(Graph->Ne));  /* 读入边数 */   
    if(Graph->Ne != 0) {/* 如果有边 */   
        E=(Edge)malloc(sizeof(struct ENode)); /* 建立边结点 */  
        /* 读入边,格式为 "起点 终点 权重” */  
        for(i=0; i<Graph->Ne; i++){  
            scanf("%d %d %d",&E->V1,&E->V2,&E->Weight);  
            /* 注意如果weight不是整形 weight的输入格式要更改*/  
            InsertEdge(Graph, E);   
        }  
    }  
    /* 如果顶点有数据的话,读入顶点数据 */   
    /*  
      for(V = 0; V < Graph->Nv; V++)  
        scanf("%c",&(Graph->G[V].Data));  
    */  
    return Graph;  
}  
int TopSort(LGraph Graph) /*拓扑排序*/  
{  
    /* Indegree计算顶各个顶点的入度 */   
    int Indegree[MaxVertexNum], cnt;  
    Vertex V;  
    PtrToAdjVNode W;  
    Queue Q = CreatQueue(Graph->Nv);  
    /* 初始化Indegree[] */  
    for( V = 0; V<Graph->Nv; V++)  
        Indegree[V]=0;  
    /* 遍历图,得到Indegree[] */  
    for( V = 0; V<Graph->Nv; V++)  
        for(W = Graph->G[V].FirstEdge; W; W = W->Next)  
            Indegree[W->AdjV]++;   //入度增加   
    /* 将所有入度为零的顶点入队列 */  
    for(V = 0;V < Graph->Nv; V++)  
        if(Indegree[V]==0)  
            AddQ(Q, V);  
    cnt = 0;    
    while(!IsEmpty(Q)){  
        V = DeleteQ(Q);  /* 弹出一个入度为零的顶点 */  
        //printf("%d\n",V);  
          
        /* 求最短工期 */  
        for(W=Graph->G[V].FirstEdge; W!=NULL; W = W->Next)  
        {  
            if(time[W->AdjV]<time[V]+W->Weight)  
                time[W->AdjV]=time[V]+W->Weight;  
        }  
          
        TopOrder[cnt++] = V; /* 将之存为结果序列的下一个元素 */   
        for(W=Graph->G[V].FirstEdge; W!=NULL; W = W->Next)  
        {  
          if(--Indegree[W->AdjV]==0)  //若删除V使得W-Adiv入度为零   
            AddQ(Q, W->AdjV);   //则此顶点入队列   
        }  
    }  
    if(cnt != Graph->Nv)  
      return  -1;  
    else   
      return   1;   
}  
int main()  
{  
    int N;  
    LGraph Graph;  
    Graph=BuildGraph();  /* 建立一个邻接表,并读入全部数据到表中 */   
    /* 之后进行拓扑排序 */   
    N=TopSort(Graph); /* 拓扑排序 */  
    if(N==1)  
    {  
        int Max=time[0];  
        for(int i=1;i<Graph->Nv;i++)  
        {  
            if(time[i]>Max)  
                Max=time[i];   
        }  
        printf("%d",Max);  
    }  
    else  
      printf("Impossible");  
    return 0;     
}  

猜你喜欢

转载自blog.csdn.net/weixin_42383680/article/details/80569674