传送门:
http://www.lydsy.com/JudgeOnline/problem.php?id=1179
Tarjan缩点+DAG上DP,水……
学习了dr神犇的代码风格,虽然一直不知道TOPL是神马意思……
Code:
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<queue>
#include<vector>
#include<stack>
using namespace std;
const int maxn=500010;
int Scc_num,Blg[maxn],s;
int sor[maxn],sor_2[maxn];
int cub[maxn],cub_2[maxn];
int n,m;
namespace Scc{
stack<int>S;
vector<int>G[maxn];
int dfn[maxn],tot,low[maxn];
void add(int u,int v){
G[u].push_back(v);
}
bool ins[maxn];
void Tarjan(int u){
dfn[u]=low[u]=++tot;
ins[u]=1;S.push(u);
for(int i=0;i<G[u].size();i++){
int v=G[u][i];
if(!dfn[v]){
Tarjan(v);
low[u]=min(low[u],low[v]);
}else
if(ins[v])
low[u]=min(low[u],dfn[v]);
}
if(dfn[u]==low[u]){
Scc_num++;
int v;
do{
v=S.top();S.pop();
ins[v]=0;
Blg[v]=Scc_num;
}while(u!=v);
}
}
};
namespace TOPL{
int f[maxn];
vector<int>G[maxn];
void add(int u,int v){
G[u].push_back(v);
}
int bfs(){
f[Blg[s]]=sor_2[Blg[s]];
queue<int>q;
q.push(Blg[s]);
while(!q.empty()){
int u=q.front();q.pop();
for(int i=0;i<G[u].size();i++){
int v=G[u][i];
if(f[v]<f[u]+sor_2[v]){
f[v]=f[u]+sor_2[v];
q.push(v);
}
}
}
int maxx=0;
for(int i=1;i<=Scc_num;i++)
if(cub_2[i])
maxx=max(maxx,f[i]);
return maxx;
}
void solve(){
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++){
int u,v;
scanf("%d%d",&u,&v);
Scc::add(u,v);
}
for(int i=1;i<=n;i++)
scanf("%d",&sor[i]);
int p;
scanf("%d%d",&s,&p);
for(int i=1;i<=p;i++)
scanf("%d",&cub[i]);
for(int i=1;i<=n;i++)
if(!Scc::dfn[i])
Scc::Tarjan(i);
for(int i=1;i<=n;i++)
sor_2[Blg[i]]+=sor[i];
for(int i=1;i<=p;i++)
cub_2[Blg[cub[i]]]=1;
for(int i=1;i<=n;i++)
for(int j=0;j<Scc::G[i].size();j++){
int v=Scc::G[i][j];
if(Blg[i]!=Blg[v])
add(Blg[i],Blg[v]);
}
printf("%d\n",bfs());
}
};
int main(){
TOPL::solve();
return 0;
}