#题目链接
#题意简述
给定一张有向图,1个起点与若干个终点,每个点可经过若干次。使到达图中的某一个终点的路径中,所经过的点的权值总和最大。求出这个最大的权值总和。
#简要做法
缩点模板题。用$Tarjan$缩点,然后在缩点图上用$SPFA$跑一遍最长路,便可得到答案。
#参考代码
|
|
|
|
|
|
using namespace std; |
const int maxn = 5e5 + 5; |
int n , m , s , l; |
int head[maxn] , te , head1[maxn] , te1; |
struct edge { |
int to , next , val; |
}e[maxn] , e1[maxn]; |
int w[maxn]; |
int low[maxn] , dfn[maxn] , belong[maxn] , cnt; |
inline void addE(int u , int v) { |
e[++te].to = v; |
e[te].next = head[u]; |
head[u] = te; |
} |
inline void add1(int u , int v , int w) { |
e1[++te1].to = v; |
e1[te1].next = head1[u]; |
head1[u] = te1; |
e1[te1].val = w; |
} |
stack <int> st; |
bool vis[maxn]; |
void tarjan(int x) { |
vis[x] = true; |
st.push(x); |
low[x] = dfn[x] = ++cnt; |
for(register int i = head[x]; i; i = e[i].next) { |
int to = e[i].to; |
if(!dfn[to]) { |
tarjan(to); |
low[x] = min(low[x] , low[to]); |
} |
if(vis[to]) |
low[x] = min(low[x] , dfn[to]); |
} |
if(low[x] == dfn[x]) { |
int t; |
do { |
t = st.top(); |
vis[t] = false; |
st.pop(); |
belong[t] = x; |
if(x != t) w[x] += w[t]; |
}while(t != x); |
} |
} |
queue <int> q; |
int dis[maxn]; |
void spfa() { |
dis[belong[s]] = w[belong[s]]; |
q.push(belong[s]); |
vis[belong[s]] = true; |
while(!q.empty()) { |
int cur = q.front(); |
q.pop(); |
vis[cur] = false; |
for(register int i = head1[cur]; i; i = e1[i].next) { |
int to = e1[i].to; |
if(dis[to] < dis[cur] + e1[i].val) { |
dis[to] = dis[cur] + e1[i].val; |
if(!vis[to]) |
q.push(to); |
vis[to] = true; |
} |
} |
} |
} |
int main() { |
scanf("%d%d" , &n , &m); |
for(register int i = 1; i <= m; ++i) { |
int u , v; |
scanf("%d%d" , &u , &v); |
addE(u , v); |
} |
for(register int i = 1; i <= n; ++i) |
scanf("%d" , &w[i]); |
scanf("%d%d" , &s , &l); |
for(register int i = 1; i <= n; ++i) |
if(!dfn[i]) tarjan(i); |
for(register int i = 1; i <= n; ++i) { |
int u = belong[i]; |
for(register int j = head[i]; j; j = e[j].next) { |
int v = belong[e[j].to]; |
if(u != v) |
add1(u , v , w[v]); |
} |
} |
spfa(); |
int bar , ans = 0; |
for(register int i = 1; i <= l; ++i) { |
scanf("%d" , &bar); |
ans = max(ans , dis[belong[bar]]); |
} |
printf("%d\n" , ans); |
return 0; |
} |
基本上就这样啦!