题目大意
给出一幅有向图每个点有价值,要从起点走到一个给定的点集中的一个点才能停止,求最大价值,重复经过没有价值。
解题思路
tarjan后按拓扑序dp即可,坑的是点可能很多要打人工栈。
code
#include<set>
#include<cmath>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define LF double
#define LL long long
#define max(n1,n2) ((n1>n2)?n1:n2)
#define min(n1,n2) ((n1>n2)?n2:n1)
#define fo(i,j,k) for(LL i=j;i<=k;i++)
#define fd(i,j,k) for(LL i=j;i>=k;i--)
using namespace std;
int const maxn=500000,maxm=500000,inf=2147483647;
LL n,m,gra,top,top2,time,s,p,u[maxm+10],v[maxm+10],val[maxm+10],to[maxm+10],
next[maxm+10],begin[maxn+10],dfn[maxn+10],low[maxn+10],st[maxn+10],st2[maxn+10],
inst[maxn+10],bel[maxn+10],save[maxn+10],f[maxn+10],pre[maxn+10];
void insert(LL u,LL v){
to[++gra]=v;
next[gra]=begin[u];
begin[u]=gra;
}
void tarjan(LL be){
inst[st[++top]=be]=1;
st2[++top2]=be;
LL now;
for(;top2;){
now=st2[top2];
if(save[st2[top2]]){
int bb;
bb++;
}
if(!dfn[now])dfn[now]=low[now]=++time;
for(;begin[now];begin[now]=next[begin[now]])
if(!dfn[to[begin[now]]]){
inst[st[++top]=st2[++top2]=to[begin[now]]]=1;
break;
}else if(inst[to[begin[now]]])low[now]=min(low[now],dfn[to[begin[now]]]);
if(!begin[now]){
if(dfn[now]==low[now]){
for(;st[top]!=now;bel[st[top]]=now,val[now]+=val[st[top]],save[now]|=save[st[top]],inst[st[top--]]=0);
bel[st[top]]=now;inst[st[top--]]=0;
}
low[st2[top2-1]]=min(low[st2[top2-1]],low[st2[top2]]);
st2[top2--];
}
}
}
int main(){
freopen("d.in","r",stdin);
freopen("d.out","w",stdout);
scanf("%lld%lld",&n,&m);
fo(i,1,m){
scanf("%lld%lld",&u[i],&v[i]);
insert(u[i],v[i]);
}
fo(i,1,n)scanf("%d",&val[i]);
scanf("%lld%lld",&s,&p);
fo(i,1,p){
LL x;scanf("%lld",&x);
save[x]=1;
}
tarjan(s);
gra=0;memset(begin,0,sizeof(begin));
fo(i,1,m)
if(bel[u[i]]&&bel[v[i]]&&bel[u[i]]!=bel[v[i]])insert(bel[u[i]],bel[v[i]]),pre[v[i]]++;
LL l=0,r=0,now;
st[++r]=s;
for(;l!=r;){
now=st[++l];
for(LL i=begin[now];i;i=next[i]){
pre[to[i]]--;
if(!pre[to[i]])inst[st[++r]=to[i]]=1;
}
}
fd(i,r,1){
now=st[i];
for(LL i=begin[now];i;i=next[i])
f[now]=max(f[now],f[to[i]]);
if(save[now]||f[now])f[now]+=val[now];
}
printf("%lld",f[s]);
return 0;
}