首页 > 代码库 > [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 }
View Code

 

 

[BZOJ1179] [Apio2009]Atm(tarjan缩点 + spfa)