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", ×[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); }