HDU_4109 Instrction Arrangement(拓扑)

题目请点我
题解:
有一系列的工作需要做,可以同时做很多工作,但是某些特定工作之间需要一定的时间间隔。现在给出了这些时间间隔,问最短需要多长时间才能把所有的工作做完。因为时间上的限制,很容易想到拓扑排序。因为是按照时间去工作,可以想像把所有的工作都放到一个时间轴上去考虑,这样我们可以利用一个优先队列去维护。
每一次找到入读为1的点,然后去更新跟当前点连接有限制的点。如果被更新点的入度变为1,则放入队列。
利用add数组将边的权值不断向后叠加,注意必须要满足的是最长的边。
测试数据:
5 3
1 2 100
1 3 2
3 4 2
5 3
1 4 5
1 3 2
3 4 1
5 3
1 4 2
1 3 5
3 4 5
7 6
1 2 3
1 3 4
2 4 5
3 4 6
4 5 7
4 6 8
代码实现:

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <queue>
#include <algorithm>
#define MAX_N 1010
#define MAX_M 10010

using namespace std;

struct node{
    int time;
    int pos;
};
int N,M;
int result;
int add[MAX_N];
int time[MAX_N];
int indegree[MAX_N];
int cost[MAX_N][MAX_N];
priority_queue<node> TD;
//优先级按照时间排列
bool operator < (const node a,const node b){
    return a.time < b.time;
}
//第一次放入队列
void inTD();
int main()
{
    //freopen("in.txt","r",stdin);
    while( scanf("%d%d",&N,&M) != EOF ){
        result = 0;
        memset(cost,-1,sizeof(cost));
        memset(add,0,sizeof(add));
        memset(time,0,sizeof(time));
        memset(indegree,0,sizeof(indegree));
        while( !TD.empty() ){
            TD.pop();
        }
        int x,y,z;
        for( int i = 0; i < M; i++ ){
            scanf("%d%d%d",&x,&y,&z);
            cost[x][y]=z;
            indegree[y]++;
        }
        inTD();
        while( !TD.empty() ){
            node start = TD.top();
            TD.pop();
            int pos = start.pos;
            //表示更新到当前节点时,当前节点的权值为之前最大的时间间隔
            time[pos] = add[pos];
            indegree[pos]--;
            //result保存所能检测到的最大时间间隔
            result = max(time[pos],result);
            for( int i = 0; i < N; i++ ){
                if( cost[pos][i] != -1 ){
                    //更新最大时间间隔
                    add[i] = max(time[pos]+cost[pos][i],add[i]);
                    indegree[i]--;
                    //若更新后入度为0就放入队列
                    if( indegree[i] == 0 ){
                        node tmp;
                        tmp.pos = i;
                        tmp.time = time[i];
                        TD.push(tmp);
                    }
                }
            }
        }
        printf("%d\n",result+1);
    }
    return 0;
}

void inTD(){
    node tmp;
    for( int i = 0; i < N; i++ ){
        if( indegree[i] == 0 ){
            tmp.pos = i;
            tmp.time = 0;
            TD.push(tmp);
        }
    }
    return ;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值