• [BZOJ] 1179: [Apio2009]Atm


    https://www.lydsy.com/JudgeOnline/problem.php?id=1179

    给定一个有向图,每个点有点权,相同的点多次经过算一次,给出起点和多个终点,问取得的最大收益。

    第一反应缩点建新图,然后就变成一个DAG了,之后就是一个最长路咯。

    #include<iostream>
    #include<cstdio>
    #include<queue>
    
    using namespace std;
    
    inline int rd(){
        int ret=0,f=1;char c;
        while(c=getchar(),!isdigit(c))f=c=='-'?-1:1;
        while(isdigit(c))ret=ret*10+c-'0',c=getchar();
        return ret*f;
    }
    
    const int MAXN=500005;
    const int INF=1<<30;
    
    struct Edge{
        int from,next,to,w;
    }e[MAXN],e2[MAXN];
    int ecnt,head[MAXN];
    inline void add(int x,int y){
        e[++ecnt].to = y;
        e[ecnt].next = head[x];
        e[ecnt].from = x;
        head[x] = ecnt;
    }
    int ecnt2,head2[MAXN];
    inline void add2(int x,int y,int w){
        e2[++ecnt2].to = y;
        e2[ecnt2].next = head2[x];
        e2[ecnt2].w = w;
        head2[x] = ecnt2;
    }
    int n,m,S,num;
    
    int savx[MAXN],savy[MAXN];
    int cost[MAXN],aims[MAXN];
    int bl[MAXN],dcc,val[MAXN];
    
    int dfn[MAXN],low[MAXN],tim;
    int ins[MAXN],sta[MAXN],top;
    void tarjan(int x){
        dfn[x]=low[x]=++tim;
        ins[sta[++top]=x]=1;
        for(int i=head[x];i;i=e[i].next){
            int v=e[i].to;
            if(!dfn[v]){
                tarjan(v);
                low[x]=min(low[x],low[v]);
            }else if(ins[v]){
                low[x]=min(low[x],dfn[v]);
            }
        }
        if(dfn[x]!=low[x]) return;
        int elm;dcc++;
        do{
            elm=sta[top--];
            bl[elm]=dcc;
            ins[elm]=0;
            val[dcc]+=cost[elm];
        }while(elm!=x);
    }
    
    queue<int> Q;
    int inq[MAXN],dis[MAXN];
    void spfa(int st){
        Q.push(st);inq[st]=1;
        while(!Q.empty()){
            int top=Q.front();Q.pop();
            inq[top]=0;
            for(int i=head2[top];i;i=e2[i].next){
                int v=e2[i].to;
                if(dis[v]<dis[top]+e2[i].w){
                    dis[v]=dis[top]+e2[i].w;
                    if(!inq[v]) Q.push(v),inq[v]=1;
                }
            }
        }
    }
    
    
    int main(){
        n=rd();m=rd();
        int x,y,w;
        for(int i=1;i<=m;i++){
            x=rd();y=rd();
            add(x,y);
        }
        for(int i=1;i<=n;i++){
            cost[i]=rd();
        }
        S=rd();num=rd();
        for(int i=1;i<=num;i++){
            aims[i]=rd();
        }
        for(int i=0;i<=n;i++) if(!dfn[i]) tarjan(i);
        for(int i=1;i<=ecnt;i++){
            int u=e[i].from,v=e[i].to;
            if(bl[u]==bl[v]) continue;
            add2(bl[u],bl[v],val[bl[v]]);
        }
        spfa(bl[S]);
        int ans=0;
        for(int i=1;i<=num;i++){
            ans=max(ans,dis[bl[aims[i]]]);
        }
        cout<<ans+val[bl[S]]<<endl;
        return 0;
    }

    本文来自博客园,作者:GhostCai,转载请注明原文链接:https://www.cnblogs.com/ghostcai/p/9364092.html

  • 相关阅读:
    抖音的服务器到底啥配置?
    三句话搞懂 Redis 缓存穿透、击穿、雪崩!
    Windows环境下安装Redis
    Redis可视化工具 Redis Desktop Manager
    Eureka自我保护机制
    Eureka介绍
    Spring Cloud OpenFeign 工作原理解析
    客户端负载均衡Ribbon:Loadbalance的源码
    spring boot中的约定优于配置
    Arrays.asList()返回的集合不能进行add,remove等操作
  • 原文地址:https://www.cnblogs.com/ghostcai/p/9364092.html
Copyright © 2020-2023  润新知