题意:给你一个有向图,每个点有一个权值,有一个起点和q个终点,没经过一个点加上这个点的权值,让你选一条路,问你最大值是多少。
思路:tarjan强连通缩个点, 然后在拓扑图上dp一下就好啦, 注意第二次建图建反向边会好一点。
1 #include<bits/stdc++.h> 2 #define LL long long 3 #define fi first 4 #define se second 5 #define mk make_pair 6 #define pii pair<int,int> 7 8 using namespace std; 9 10 const int N=5e5+7; 11 const int M=1e4+7; 12 const int inf=0x3f3f3f3f; 13 const LL INF=0x3f3f3f3f3f3f3f3f; 14 const int mod=1e9 + 7; 15 16 struct edge { 17 int from, to, nx; 18 }e[N]; 19 bool bar[N], flag[N], in[N], ok[N]; 20 int n, m, tot, cnt, S, p, idx, top, head[N], a[N], sum[N], dfn[N], low[N], id[N], f[N], st[N]; 21 22 vector<int> edge[N]; 23 void add(int from, int to) { 24 e[tot].from = from; 25 e[tot].to = to; 26 e[tot].nx = head[from]; 27 head[from] = tot++; 28 } 29 30 void tarjan(int u) { 31 ++idx; 32 dfn[u] = low[u] = idx; 33 st[top++] = u; in[u] = true; 34 for(int i = head[u]; ~i; i = e[i].nx) { 35 int v = e[i].to; 36 if(!dfn[v]) { 37 tarjan(v); 38 low[u] = min(low[u], low[v]); 39 } else if(in[v]) { 40 low[u] = min(low[u], dfn[v]); 41 } 42 } 43 if(low[u] == dfn[u]) { 44 cnt++; 45 while(1) { 46 int now = st[--top]; 47 in[now] = false; 48 id[now] = cnt; 49 if(now == u) break; 50 } 51 } 52 } 53 54 int dp(int u) { 55 if(f[u] != -1) return f[u]; 56 f[u] = 0; 57 for(int i = 0; i < edge[u].size(); i++) { 58 int v = edge[u][i]; 59 int ret = dp(v); 60 if(ok[v]) { 61 ok[u] = true; 62 f[u] = max(f[u], f[v]); 63 } 64 } 65 if(!ok[u]) return f[u]; 66 return f[u] = f[u] + sum[u]; 67 } 68 int main() { 69 memset(head, -1, sizeof(head)); 70 memset(f, -1, sizeof(f)); 71 scanf("%d%d", &n, &m); 72 for(int i = 1; i <= m; i++) { 73 int from, to; scanf("%d%d", &from, &to); 74 add(from, to); 75 } 76 for(int i = 1; i <= n; i++) 77 scanf("%d", &a[i]); 78 79 scanf("%d%d", &S, &p); 80 for(int i = 1; i <= p; i++) { 81 int x; scanf("%d", &x); 82 flag[x] = true; 83 } 84 for(int i = 1; i <= n; i++) { 85 if(!dfn[i]) tarjan(i); 86 } 87 for(int i = 1; i <= n; i++) { 88 sum[id[i]] += a[i]; 89 bar[id[i]] |= flag[i]; 90 } 91 for(int i = 0; i < tot; i++) { 92 int u = e[i].from, v = e[i].to; 93 if(id[u] != id[v]) { 94 edge[id[v]].push_back(id[u]); 95 } 96 } 97 S = id[S]; 98 ok[S] = true; 99 int ans = 0; 100 for(int i = 1; i <= cnt; i++) { 101 if(bar[i]) { 102 ans = max(ans, dp(i)); 103 } 104 } 105 printf("%d ", ans); 106 return 0; 107 } 108 /* 109 */