zoukankan      html  css  js  c++  java
  • ATM(BZOJ 1179)

    测评传送门

    题意:

    给你一个有向无环图,每个点有一个权值,给定起点,和多个终点。

    求到达终点的最大权值。

    输入

    6 7 
    1 2 
    2 3 
    3 5 
    2 4 
    4 1 
    2 6 
    6 5 
    10 12 8 16 1 5 
    1 4 
    4 3 5 6 

    输出

    47 

     


    思路:

    Tarjan 缩点,点权转边权,跑SPFA

    感谢nan葛格的博客讲解

    code

    #include<stdio.h> 
    #include<stack>
    #include<queue>
    #include<algorithm> 
    using namespace std;
    const int mxn=510000;
    struct Edge {
        int to,next;
    }e[mxn<<1],E[mxn<<1];
    int n,m,cnt,idx,tot,st,k,ans;
    int first[mxn<<1],dfn[mxn],low[mxn],w[mxn],W[mxn],bel[mxn],dis[mxn],head[mxn<<1];
    bool ins[mxn],vis[mxn];
    stack<int> stk;
    queue<int> q;
    void add(int from,int to) {
        e[++cnt].to=to;
        e[cnt].next=first[from];
        first[from]=cnt;
    }
    
    void Tarjan(int x) 
    {
        dfn[x]=low[x]=++idx;
        ins[x]=1;stk.push(x);
        for(int i=first[x];i;i=e[i].next) {
            int to=e[i].to;
            if(!dfn[to]) {
                Tarjan(to);
                low[x]=min(low[x],low[to]);
            } 
            else if(ins[to]) low[x]=min(low[x],dfn[to]);
         }
        if(low[x]==dfn[x]) {
            tot++;
            int top;
            do {
                top=stk.top();stk.pop();
                ins[top]=0;
                bel[top]=tot;
            }while(top!=x);
        }
    }
    
    void rebuild() 
    { 
        for(int x=1;x<=n;++x) {
            for(int i=first[x];i;i=e[i].next) {
                int to=e[i].to;
                if(bel[x]==bel[to]) continue;
                E[++cnt].to=bel[to];
                E[cnt].next=head[bel[x]];
                head[bel[x]]=cnt;
            }
            W[bel[x]]+=w[x];
        }
    }
    
    void spfa() 
    {
        dis[bel[st]]=W[bel[st]];
        q.push(bel[st]);
        while(!q.empty()) {
            int x=q.front();q.pop();
            vis[x]=0;
            for(int i=head[x];i;i=E[i].next) 
            {
                int to=E[i].to;
                if(dis[x]+W[to]>dis[to]) {
                    dis[to]=dis[x]+W[to];
                    if(!vis[to]) {
                        vis[to]=1;
                        q.push(to);
                    }
                }
            }
        }
    }
       
    int main() 
    {
        scanf("%d%d",&n,&m);
        for(int i=1;i<=m;++i) {
            int from,to;    
            scanf("%d%d",&from,&to);
            add(from,to);
        }
        for(int i=1;i<=n;++i) {
            scanf("%d",&w[i]);
            if(!dfn[i]) Tarjan(i);
        }
        cnt=0;
        rebuild();
        scanf("%d%d",&st,&k);
        spfa();
        for(int i=1;i<=k;++i) {
            int x;
            scanf("%d",&x);
            ans=max(ans,dis[bel[x]]);
        }
        printf("%d",ans);
        return 0;
    }
    /*
    6 7 
    1 2 
    2 3 
    3 5 
    2 4 
    4 1 
    2 6 
    6 5 
    10 12 8 16 1 5 
    1 4 
    4 3 5 6 
    */
  • 相关阅读:
    Spring定时
    随记生成验证码
    缅怀过去
    java运行可以执行文件
    随 记
    TLD生成
    IT鸟的回忆录
    梦之物语
    VINSMono
    WIDOWX 250 6DOF
  • 原文地址:https://www.cnblogs.com/qseer/p/9831711.html
Copyright © 2011-2022 走看看