[POJ3249]Test for Job [拓扑排序+DAG上的最长路径]

给定一张带点权的DAG 求一条入度为0节点到出度为0节点的最长路

把点权转化为边权(同时多源转化成单源):边u->v的权值为W[v],这样入度为0的节点权值会被遗漏,新开一个点0向入度为0的点u连有向边,权值为W[u],这样就只有0是入度为0的点了。

先进行拓扑排序,再求出最长路径(利用DAG分层的性质可以在线性时间内求出最长路)

 1 #include <iostream>
 2 #include <algorithm>
 3 #include <cstring>
 4 #include <cmath>
 5 #include <cstdio>
 6 using namespace std;
 7 typedef long long LL;
 8 
 9 template<class T> void read(T & x){
10   register int c = getchar(), f = 1; x = 0;
11   while(!isdigit(c)){if (c == '-') f = -1; c = getchar();}
12   while(isdigit(c)) x = x*10+(c&15), c = getchar();
13   x *= f;
14 }
15 const int N = 100005;
16 struct Edge{int v, w, next;}G[N*20];
17 int n, m, s, head[N], tot,  ind[N], out[N], W[N]; LL dis[N], ans = -123023423423;
18 void toposort(int s) {
19   int topo[N], cnt = 0;
20   topo[++cnt] = 0;
21   for(int k = 0; k <= cnt; ++k)
22     for(int i = head[topo[k]]; i; i = G[i].next) {
23       int v = G[i].v;
24       ind[v]--;
25       if (ind[v]==0) topo[++cnt] = v;
26     }
27   memset(dis,0xc0,sizeof(dis));dis[s] = 0;
28   for(int k = 0; k <= cnt; ++k)
29     for(int i = head[topo[k]]; i; i = G[i].next) {
30       int v = G[i].v, w = G[i].w;
31       dis[v] = max(dis[topo[k]]+w, dis[v]);
32     }
33 }
34 
35 inline void add(int u, int v, int w) {
36   G[++tot].v=v, G[tot].w=w, G[tot].next=head[u];head[u]=tot;
37   ind[v]++, out[u]++;
38 }
39 
40 int main(void){
41   while(scanf("%d%d", &n, &m) == 2){
42     memset(head,0,sizeof(head));tot=0;memset(ind,0,sizeof(ind));memset(out,0,sizeof(out));
43     ans = 0xc0c0c0c0c0c0c0c0;
44     for(int i = 1; i <= n; ++i) read(W[i]);
45     for(int u, v, i = 1; i <= m; ++i) {
46       read(u), read(v);
47       add(u, v, W[v]);
48     } 
49     for(int i = 1; i <= n; ++i) {
50       if (!ind[i]) add(0,i,W[i]);
51     }
52     toposort(s);
53     for(int i = 1; i <= n; ++i) {
54       if (!out[i]) ans = max(ans, dis[i]);
55     }
56     cout << ans << '
';
57   }
58   return 0;
59 }
View Code
原文地址:https://www.cnblogs.com/storz/p/8550884.html