首页 > 代码库 > [BZOJ1179] [Apio2009]Atm(tarjan缩点 + spfa)
[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)
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。