课堂练习:ATM
考虑缩点然后跑最长路。
注意本题限定了起点和终点。
如果直接采用拓扑排序,然后从起点开始搜,是不对的。
加粗点为起点,发现1点入度为2,那么直接搜会发现1点根本不会加入队列。
此时,我们可以找出起点可到的点对应的分支,再进行计算。
#include<cstdio>
#include<algorithm>
#include<cassert>
#include<cstring>
using namespace std;
#define Ed for(int i=h[x];~i;i=ne[i])
#define Ls(i,l,r) for(int i=l;i<r;++i)
#define Rs(i,l,r) for(int i=l;i>r;--i)
#define Le(i,l,r) for(int i=l;i<=r;++i)
#define Re(i,l,r) for(int i=l;i>=r;--i)
#define L(i,l) for(int i=0;i<l;++i)
#define E(i,l) for(int i=1;i<=l;++i)
#define W(t) while(t--)
#define Wh while
const int N=500010,M=N;
int dp[N],q[N],s,p,in[N],cur,tim,h[N],e[M],ne[M],idx,n,m,a[N],dfn[N],low[N],id[N],scc_cnt,sz[N],stk[N],top;//don't forget memset h!
bool ins[N],ish[N];
struct tmpe{
int a,b;
}tmp[N];
void add(int a,int b){
// printf("%d %d sz[a]=%d,sz[b]=%d\n",a,b,sz[a],sz[b]);
e[idx]=b,ne[idx]=h[a],h[a]=idx++;
}
void tarjan(int x){
dfn[x]=low[x]=++tim;
ins[x]=1;
stk[++top]=x;
Ed{
int j=e[i];
if(!dfn[j]){
tarjan(j);
low[x]=min(low[x],low[j]);
}
else if(ins[j])low[x]=min(low[x],dfn[j]);
}
if(dfn[x]==low[x]){
++scc_cnt;
int y;
do{
y=stk[top--];
ins[y]=0;
id[y]=scc_cnt;
sz[scc_cnt]+=a[y];
}Wh(x!=y);
}
}
void topo(){
int hh=0,tt=0;
q[tt++]=id[s];
dp[id[s]]=sz[id[s]];
Wh(hh!=tt){
int x=q[hh++];
// printf("dp[%d]=%d\n",x,dp[x]);
Ed{
int j=e[i];
dp[j]=max(dp[j],dp[x]+sz[j]);
// assert(in[j]>1);
if(!--in[j])q[tt++]=j;
}
}
int ans=0;
E(i, p){
int x;
scanf("%d",&x);
ans=max(ans,dp[id[x]]);
}
printf("%d",ans);
}
void bfs(){
int hh=0,tt=0;
q[tt++]=id[s];
ish[id[s]]=1;
Wh(hh!=tt){
int x=q[hh++];
Ed{
int j=e[i];
if(!ish[j])ish[j]=1,q[tt++]=j;
}
}
}
int main(){
#ifndef ONLINE_JUDGE
freopen("1.in","r",stdin);
#endif
scanf("%d%d",&n,&m);
memset(h,-1,n*4+4);
E(i, m){
int a,b;
scanf("%d%d",&a,&b);
add(a,b);
}
E(i, n)scanf("%d",a+i);
E(i, n)
if(!dfn[i])tarjan(i);
E(x, n)
Ed{
int j=e[i];
if(id[x]==id[j])continue;
tmp[++cur]={id[x],id[j]};
}
memset(h,-1,scc_cnt*4+4);
idx=0;
// puts("大大");
scanf("%d%d",&s,&p);
E(i, cur){
int a=tmp[i].a,b=tmp[i].b;
add(a,b);
}
bfs();
memset(h,-1,scc_cnt*4+4);
E(i, cur){
int a=tmp[i].a,b=tmp[i].b;
if(!ish[a])continue;
add(a,b),++in[b];
}
topo();
return 0;
}
本文作者:wscqwq
本文链接:https://www.cnblogs.com/wscqwq/p/17678001.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步