拓朴排序,关键路径

 1)拓朴排序:有向无环图;

/**
    1)拓朴排序:有向无环图;
    vector<int> Adj[maxn]; //邻接表
    int inDegree[maxn];  //入度数组
    int Nv,Ne; //顶点数,边数;

    bool topSort()
    {
        int num=0;
        queue<int> q;
        for(int i=0;i<Nv;++i)
        {
            if(inDegree[i]==0)
                q.push(i);
        }

        while(!q.empty())
        {
            int u=q.front();
            printf("%d ",u);
            q.pop();
            for(int i=0;i<Adj[u].size();++i)
            {
                int v=Adj[u][i];
                inDegree[v]--;
                if(indegree[v] == 0)
                    q.push(v);
            }
            ++num;
        }

        if(num == Nv)
            return true;
        retuen false;
    }
*/

2) e[r],l[r]:分别表示活动 ar 的最早开始时间和最迟开始时间;
    当e[r] == l[r] 说明活动 ar 是关键活动;

    ve[i],vl[i] : 表示事件 i 的最早发生时间和最迟发生时间;

    事件 Vi 经过活动 ar 到达 事件 Vj;那么 e[r]=ve[i], l[r]=vl[j]-length[r];
*/

/**

    3) 通过前驱节点 ve[il] ~ ve[ik]的值更新 ve[j]的值:ve[j] = max{ve[ip] + length[rp]};

 


/**
    2) e[r],l[r]:分别表示活动 ar 的最早开始时间和最迟开始时间;
    当e[r] == l[r] 说明活动 ar 是关键活动;

    ve[i],vl[i] : 表示事件 i 的最早发生时间和最迟发生时间;

    事件 Vi 经过活动 ar 到达 事件 Vj;那么 e[r]=ve[i], l[r]=vl[j]-length[r];
*/

/**

    3) 通过前驱节点 ve[il] ~ ve[ik]的值更新 ve[j]的值:ve[j] = max{ve[ip] + length[rp]};

    代码:
    //拓朴排序,顺便求ve数组;
    stack<int> topOrder;  //用栈存储拓朴排序的结果,方便后面计算vl 数组;

    bool topSort()
    {
        queue<int> q;
        for(int i=0;i<n;++i)
        {
            if(inDegree[i]==0)
                q.push(i);
        }

        while(!q.empty())
        {
            int u=q.front();
            q.pop();
            topOrder.push(u);
            for(int i=0;i<Adj[u].size();++i)
            {
                int v=Adj[u][i].v;
                inDegree[v]--;
                if(inDegree[v]==0)
                   1)拓朴排序:有向无环图; q.push(v);

                if(ve[u]+Adj[u][i].cost > ve[v])
                    ve[v]=ve[u]+Adj[u][i].cost;
            }
        }

        if(topOrder.size() == n)
            return true;
        else
            return false;
    }
*/

 4) 通过 vi的后继节点 vjl~vjk 来推出vi的值: vi = min{vl[jp]-length[rp]};

/**
    4) 通过 vi的后继节点 vjl~vjk 来推出vi的值: vi = min{vl[jp]-length[rp]};

    代码:
    stack<int> topOrder;  //用栈存储拓朴排序的结果,方便后面计算vl 数组;

    bool topSort()
    {
        queue<int> q;
        for(int i=0;i<n;++i)
        {
            if(inDegree[i]==0)
                q.push(i);
        }

        while(!q.empty())
        {
            int u=q.front();
            q.pop();
            topOrder.push(u);
            for(int i=0;i<Adj[u].size();++i)
            {
                int v=Adj[u][i].v;
                inDegree[v]--;
                if(inDegree[v]==0)
                    q.push(v);

                if(ve[u]+Adj[u][i].cost > ve[v])
                    ve[v]=ve[u]+Adj[u][i].cost;
            }
        }

        int Size=topOrder.size();
        
        fill(vl,vl+n,ve[n-1]);
        while(!topOrder.empty())
        {
            int u=topOrder.top();
            topOrder.pop();
            for(int i=0;i<Adj[u].size();++i)
            {
                int v=Adj[u][i].v;

                if(vl[v] - Adj[u][i].cost < vl[u])
                    vl[u] = vl[v] - Adj[u][i].cost;
            }
        }

        if(Size == n)
            return true;
        else
            return false;
    }

*/

 5)求关键路径长度;
    关键路径,不是有向无环图返回-1,否则返回关键路径长度;


/**
    5)求关键路径长度;
    关键路径,不是有向无环图返回-1,否则返回关键路径长度;

    代码:
    int CriticalPath()
    {
        memset(ve,0,sizeof(ve));
        if(topSort() == false)
            return -1;

        fill(vl,vl+n,ve[n-1]);
        while(!topOrder.empty())
        {
            int u=topOrder.top();
            topOrder.pop();
            for(int i=0;i<Adj[u].size();++i)
            {
                int v=Adj[u][i].v;
                if(vl[v] - Adj[u][i].cost < vl[u])
                    vl[u]=vl[v] - Adj[u][i].cost;
            }
        }

        for(int u=0;u<n;++u)
            for(int i=0;i<Adj[u].size();++i)
            {
                int v=Adj[u][i].v , cost=Adj[u][i].cost;
                int e=ve[u] , l=vl[v]-cost;

                if(e == l)
                    printf("%d->%d\n",u,v);
            }

        return ve[n-1];
    }

*/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
拓扑排序是一种用于有向无环图(DAG)的排序算法。在DAG中,每个节点代表一个任务,边表示任务间的依赖关系,即若任务A依赖于任务B,则边从B指向A。拓扑排序将DAG中的所有任务排成一个线性序列,使得对于任意一对有依赖关系的任务,其排列顺序都符合依赖关系。 以下是用数组表示法实现拓扑排序的C语言代码: ```c #include <stdio.h> #define MAXN 100 // 最大节点数 int n; // 节点数 int G[MAXN][MAXN]; // 邻接矩阵表示有向图 int inDegree[MAXN]; // 记录每个节点的入度 int queue[MAXN]; // 用于拓扑排序的队列 int front, rear; // 队列的头尾指针 void topoSort() { int i, j, k; // 初始化队列 front = rear = 0; for (i = 0; i < n; i++) { if (inDegree[i] == 0) { queue[rear++] = i; } } // 拓扑排序 while (front < rear) { int u = queue[front++]; // 取出队首节点 printf("%d ", u); // 输出节点编号 for (j = 0; j < n; j++) { if (G[u][j]) { // 若u->j有一条边 if (--inDegree[j] == 0) { // j的入度减1 queue[rear++] = j; // 若j的入度为0,则入队 } } } } printf("\n"); } int main() { int i, j, u, v; scanf("%d", &n); for (i = 0; i < n; i++) { for (j = 0; j < n; j++) { G[i][j] = 0; // 初始化邻接矩阵 } inDegree[i] = 0; // 初始化入度数组 } // 读入有向边,构建邻接矩阵 while (scanf("%d%d", &u, &v) != EOF) { G[u][v] = 1; inDegree[v]++; } // 拓扑排序 topoSort(); return 0; } ``` 该代码通过邻接矩阵表示有向图,使用一个数组记录每个节点的入度,使用一个队列进行拓扑排序。在每次排序中,将入度为0的节点加入队列中,然后依次取出队首节点,输出其编号,并将与它相邻的节点的入度减1,若减1后入度为0,则将该节点入队。直到队列为空为止。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值