qq

课堂练习:ATM

image-20230904201200696

考虑缩点然后跑最长路。

注意本题限定了起点和终点。

如果直接采用拓扑排序,然后从起点开始搜,是不对的。

image-20230904201445530

加粗点为起点,发现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 中国大陆许可协议进行许可。

posted @   wscqwq  阅读(7)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起