P1113 杂务 【拓扑排序】

题目

https://www.luogu.com.cn/problem/P1113

 

 

 

 思路

这道题是用顶点表示活动,应该是一个AOV网,但是不要担心,它的拓扑排序与AOE网的差不多

具体的方法就是它不像AOE网那样给的直接是边的权值,而是给的点的权值,所以我们先使用一个times数组记录下来每个节点代表的活动的时间,然后记录图的连接关系,并且把点的入度记录下来

之后入度为零的入队,用一个数组answer来表示活动的最早完成时间

注意该表达式:

answer[y] = max(answer[y], answer[t] + times[y]);

这个起的效果是在入度大于1的节点中,选择时间最晚的(必须都做完)

PS:拓扑排序与关键路径区别:关键路径使用两次拓扑排序

代码

#include<iostream>
#include<cstdio>
#include<queue>
#include<algorithm>
using namespace std;
#define maxn 10005
#define maxm 50000
struct node
{
    int to;
    int next;
}e[maxm];
int head[maxn],times[maxn], answer[maxn], in[maxn];
int n,cnt=0;
void addedge(int u,int v)
{
    cnt++;
    e[cnt].to = v;
    e[cnt].next = head[u];
    head[u] = cnt;
}
int main()
{
    scanf("%d", &n);
    for (int i = 1; i <= n; i++)
    {
        int a, c;
        scanf("%d", &a);
        scanf("%d", &times[a]);
        scanf("%d", &c);
        while (c)
        {
            addedge(c, a);
            in[a]++;
            scanf("%d", &c);
        }
    }
    queue<int>q;
    for (int i = 1; i <= n; i++)
    {
        if (in[i] == 0)
        {
            answer[i] = times[i];
            q.push(i);
        }
    }
    int maxx = -1;
    while (!q.empty())
    {
        int t = q.front(); q.pop();
        for (int i = head[t]; i; i = e[i].next)
        {
            int y = e[i].to;
            in[y]--;
            if (in[y] == 0)q.push(y);
            answer[y] = max(answer[y], answer[t] + times[y]);
        }
    
    }
    for (int i = 1; i <= n; i++)
        maxx = max(maxx, answer[i]);
    printf("%d", maxx);
}

 

 
posted @ 2020-06-29 19:54  Jason66661010  阅读(174)  评论(0编辑  收藏  举报