PAT : 数据结构与算法题目集(中文)7-11 关键活动

#include <algorithm>
#include <iostream>
#include <queue>
#include <set>
#include <vector>
using namespace std;
using pairint = pair<int, int>;
const int INF = 0x3F3F3F3F;
int getdigit(void)
{
    int temp{0};
    while (1)
    {
        char ch = getchar();
        if (ch == ' ' || ch == '\n' || ch == EOF)
            return temp;
        temp = temp * 10 + ch - '0';
    }
}
int main(int argc, char *argv[])
{
    int N{getdigit()}, M{getdigit()}, TN{0};
    vector<vector<pairint>> Ver(N + 1);
    vector<vector<pairint>> reVer(N + 1);
    vector<int> InKey(N + 1);
    vector<int> OutKey(N + 1);
    vector<int> InNext(N + 1), OutNext(N + 1, INF);
    queue<int> Q;
    int Tmax{0};
    while (M--)
    {
        int a{getdigit()}, b{getdigit()}, value{getdigit()};
        Ver[a].push_back({b, value});
        reVer[b].push_back({a, value});
        ++OutKey[a];
        ++InKey[b];
    }
    for (int i = 1; i <= N; ++i)
        if (!InKey[i])
        {
            Q.push(i);
            InNext[i] = 0;
        }
    while (!Q.empty())
    {
        int Vertex = Q.front();
        Q.pop();
        ++TN;
        for (const auto &i : Ver[Vertex])
        {
            if (--InKey[i.first] == 0)
                Q.push(i.first);
            InNext[i.first] = max(InNext[i.first], InNext[Vertex] + i.second);
            Tmax = max(Tmax, InNext[i.first]);
        }
    }
    if (TN != N)
    {
        printf("0\n");
        return EXIT_SUCCESS;
    }
    printf("%d\n", Tmax);
    for (int i = 1; i <= N; ++i)
        if (!OutKey[i])
        {
            Q.push(i);
            OutNext[i] = Tmax;
        }
    while (!Q.empty())
    {
        int Vertex = Q.front();
        Q.pop();
        for (const auto &i : reVer[Vertex])
        {
            if (--OutKey[i.first] == 0)
                Q.push(i.first);
            OutNext[i.first] = min(OutNext[i.first], OutNext[Vertex] - i.second);
        }
    }
    for (int i = 1; i <= N; ++i)
    {
        for (auto j = Ver[i].rbegin(); j != Ver[i].rend(); ++j)
        {
            int temp{OutNext[(*j).first] - InNext[i] - (*j).second};
            if (!temp)
                printf("%d->%d\n", i, (*j).first);
        }
    }
    return EXIT_SUCCESS;
}

比较麻烦的一类问题,求关键路径就是计算每条边是否有松弛时间。

A -> B 松弛时间 = B 的最晚完成时间 - A 的最早完成时间 - 边消耗的时间

拓扑排序列出节点访问顺序(拓扑排序感觉上就是BFS变种),从入度为 0 的节点开始遍历得到所有节点的最短完成时间;遍历期间统计出现的最大时间 Tmax。

当发现队列清空后节点未全部访问,表明出现未连通,立即输出错误信息退出程序!

将所有出度为 0 的节点都初始化为最晚完成时间是上面求出的 Tmax,反向拓扑排序列出访问顺序,遍历得到所有节点的最晚完成时间。

遍历所有边,计算它们的松弛时间,松弛时间为 0 的边输出。

**注意:题目中说的这句话(任务开始的交接点编号小者优先,起点编号相同时,与输入时任务的顺序相反)

这啥意思呢? (就是字面意思2333,一开始没看明白~)

我们用邻接表不是存了所有边的信息了嘛。起点编号小优先,就是起始点从小到大遍历;与输入时顺序相反,就是与邻接表存入数据的顺序相反。(我用的 vector 存邻接表,存入顺序是 push_back ,输出就用反向迭代器 rbegin和rend 输出~)

 

END

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值