[BZOJ1179] [Apio2009]Atm(tarjan缩点 + spfa)
Posted 蒟蒻zht的博客
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[BZOJ1179] [Apio2009]Atm(tarjan缩点 + spfa)相关的知识,希望对你有一定的参考价值。
题意
N个点M条边的有向图
每个点有点权
从某一个结点出发
问能获得的最大点权和
一个点的点权最多被计算一次
N<=500000 M<=500000
思路
先tarjan缩点,然后就形成一个dag,无环,所以直接spfa求最长路就行。
也可以先缩点,然后拓扑排序 + dp 搞。
代码
1 #include <map> 2 #include <queue> 3 #include <stack> 4 #include <cstdio> 5 #include <cstring> 6 #include <iostream> 7 8 const int MAXN = 500001; 9 int n, m, s, p, cnt, cnt1, tim, sz, ans; 10 int head[MAXN], to[MAXN], next[MAXN], head1[MAXN], to1[MAXN], next1[MAXN]; 11 int a[MAXN], dfn[MAXN], low[MAXN], belong[MAXN], val[MAXN], dis[MAXN]; 12 bool ins[MAXN], vis[MAXN]; 13 std::map <int, int> map1[MAXN]; 14 std::stack <int> S; 15 std::queue <int> q; 16 17 inline int max(int x, int y) 18 { 19 return x > y ? x : y; 20 } 21 22 inline int min(int x, int y) 23 { 24 return x < y ? x : y; 25 } 26 27 inline int read() 28 { 29 int f = 1, x = 0; 30 char ch = getchar(); 31 for(; !isdigit(ch); ch = getchar()) if(ch == ‘-‘) f = -1; 32 for(; isdigit(ch); ch = getchar()) x = (x << 1) + (x << 3) + ch - ‘0‘; 33 return f * x; 34 } 35 36 inline void add(int x, int y) 37 { 38 to[cnt] = y; 39 next[cnt] = head[x]; 40 head[x] = cnt++; 41 } 42 43 inline void add1(int x, int y) 44 { 45 to1[cnt1] = y; 46 next1[cnt1] = head1[x]; 47 head1[x] = cnt1++; 48 } 49 50 inline void dfs(int u) 51 { 52 int i, v; 53 S.push(u); 54 ins[u] = 1; 55 dfn[u] = low[u] = ++tim; 56 for(i = head[u]; i ^ -1; i = next[i]) 57 { 58 v = to[i]; 59 if(!dfn[v]) 60 { 61 dfs(v); 62 low[u] = min(low[u], low[v]); 63 } 64 else if(ins[v]) low[u] = min(low[u], dfn[v]); 65 } 66 if(!(low[u] ^ dfn[u])) 67 { 68 sz++; 69 do 70 { 71 v = S.top(); 72 S.pop(); 73 belong[v] = sz; 74 ins[v] = 0; 75 } 76 while(u ^ v); 77 } 78 } 79 80 inline void spfa() 81 { 82 int i, u, v; 83 dis[belong[s]] = val[belong[s]]; 84 q.push(belong[s]); 85 vis[belong[s]] = 1; 86 while(!q.empty()) 87 { 88 u = q.front(); 89 q.pop(); 90 vis[u] = 0; 91 for(i = head1[u]; i ^ -1; i = next1[i]) 92 { 93 v = to1[i]; 94 if(dis[v] < dis[u] + val[v]) 95 { 96 dis[v] = dis[u] + val[v]; 97 if(!vis[v]) 98 { 99 vis[v] = 1; 100 q.push(v); 101 } 102 } 103 } 104 } 105 } 106 107 int main() 108 { 109 int i, x, y, u, v; 110 n = read(); 111 m = read(); 112 memset(head, -1, sizeof(head)); 113 memset(head1, -1, sizeof(head1)); 114 for(i = 1; i <= m; i++) 115 { 116 x = read(); 117 y = read(); 118 add(x, y); 119 } 120 for(i = 1; i <= n; i++) a[i] = read(); 121 s = read(); 122 p = read(); 123 dfs(s); 124 for(i = 1; i <= n; i++) val[belong[i]] += a[i]; 125 for(u = 1; u <= n; u++) 126 for(i = head[u]; i ^ -1; i = next[i]) 127 { 128 v = to[i]; 129 if(belong[u] ^ belong[v] && !map1[belong[u]][belong[v]]) 130 map1[belong[u]][belong[v]] = 1, add1(belong[u], belong[v]); 131 } 132 spfa(); 133 for(i = 1; i <= p; i++) 134 { 135 x = read(); 136 ans = max(ans, dis[belong[x]]); 137 } 138 printf("%d\n", ans); 139 return 0; 140 }
以上是关于[BZOJ1179] [Apio2009]Atm(tarjan缩点 + spfa)的主要内容,如果未能解决你的问题,请参考以下文章
缩点+spfa最长路bzoj 1179: [Apio2009]Atm