码迷,mamicode.com
首页 > 编程语言 > 详细

hdu Instrction Arrangement(关键路径 + 拓扑排序)

时间:2016-08-11 13:05:56      阅读:228      评论:0      收藏:0      [点我收藏+]

标签:

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2586

题意:

5 2                     //5个进程(编号从 0 开始)需要被执行,有2个约束条件, 问全部执行完成的最短时间。
1 2 1                   //1号要在2号进程执行完成的后一纳秒执行
3 4 1
 
Sample Output
2
 
关键路径:
  基于AOE网(Activity On Edge),也就是说,每一条边代表着一个事件的发生,边的权值即为事件的花费时间。
节点可以抽象理解为一个状态。在拓扑序列中,后面的状态是由前面的状态经过事件的发生(边)到达的,从 0 节点(什么都没做)到 n - 1 (完成 n 个事件)的状态。
关键路径是由关键节点组成的路径,关键路径上所需时间为完成这个工程(n 个事件)最少花费时间。
 
可以用来解决的问题:eg,有一项工程,工程有 n 个事件,有些可以同步发生,而有些有先后执行的顺序限制, 问完成工程的最少时间?
 
关键节点:
  要想在最短时间完成工程,那么关键节点的最早发生时间和最晚发生时间是相同的。这需要正反两次拓扑排序。
 
思路:
  这道题只需要正向拓扑排序,求出关键路径上所需时间即可。
  对于输入:
    5 3
    0 1 3
    1 2 4    //可以理解为从 2 号状态(已经完成了事件 2 和事件 0 的状态)花费间隔 3 纳秒,可以到达 1 状态。
    3 4 3
 
#include <stdio.h>
#include <queue>
#include <math.h>
#include <string.h>
#include <algorithm>
using namespace std;

const int N = 1007;

typedef struct Edge
{
    int w;
    int to;
    int next;
}edge;
edge eg[N * 10];

int n, m, head[N], isVis[N], in[N], out[N], val[N];  //val记录每个状态的时间,记录到达当前状态最长的时间
queue <int> q;

int criticalPath()
{
    int max = -1;
    while (!q.empty())
        q.pop();
    memset(val, 0, sizeof(val));
    for (int i = 0; i < n; i++)
    {
        if (!in[i])
        {
            val[i] = 1;
            q.push(i);
            isVis[i] = 1;
        }
    }
    while (!q.empty())
    {
        int temp = q.front();
        q.pop();
        if (val[temp] > max)
            max = val[temp];
        int r = head[temp];
        while (r != -1)
        {
            in[eg[r].to]--;
            if (val[eg[r].to] < val[temp] + eg[r].w - 1)
                val[eg[r].to] = val[temp] + eg[r].w - 1;
            if (!in[eg[r].to] && !isVis[eg[r].to])
            {
                val[eg[r].to]++;
                isVis[eg[r].to] = 1;
                q.push(eg[r].to);
            }
            r = eg[r].next;
        }
    }
    return max;
}

int main()
{
    while (scanf("%d%d", &n, &m) != EOF)
    {
        memset(isVis, 0, sizeof(isVis));
        memset(head, -1, sizeof(head));
        for (int i = 1; i <= m; i++)
        {
            int u, v, w;
            scanf("%d%d%d", &v, &u, &w);
            eg[i].to = v;
            eg[i].w = w;
            in[v]++;
            out[u]++;
            eg[i].next = head[u];
            head[u] = i;
        }
        printf("%d\n", criticalPath());
    }
    return 0;
}

 

hdu Instrction Arrangement(关键路径 + 拓扑排序)

标签:

原文地址:http://www.cnblogs.com/burning-flame/p/5760356.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!