1. 程式人生 > >[POJ3249]Test for Job [拓撲排序+DAG上的最長路徑]

[POJ3249]Test for Job [拓撲排序+DAG上的最長路徑]

-- poj3249 src event AD memset toposort amp topo

給定一張帶點權的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 << \n; 57 } 58 return 0; 59 }
View Code

[POJ3249]Test for Job [拓撲排序+DAG上的最長路徑]