zoukankan      html  css  js  c++  java
  • BZOJ1179 [Apio2009]Atm Tarjan 强连通缩点 动态规划

    欢迎访问~原文出处——博客园-zhouzhendong

    去博客园看该题解


    题目传送门 - BZOJ1179


    题意概括

      有一个有向图,每一个节点有一个权值,其中有一些结束点。

      现在,你要从S出发,到达任意一个结束点,使得经过的节点的权值和最大(可以重复经过某一个节点,但是权值只记入一次)。


    题解

      小码农题。

      如果有强连通分量,那么之间的点是可以全部拿到的,傻子才不拿。

      所以先Tarjan强连通缩个点。

      然后就是一个DAG(有向无环图)了。

      那么就是一个记忆化dfs的问题了。

      于是就简单了。

      but,尴尬的我犯了低级错误,又wa了一次……

      


    代码

    #include <cstring>
    #include <algorithm>
    #include <cstdio>
    #include <cstdlib>
    #include <cmath>
    using namespace std;
    const int N=500000+5;
    const int Inf=2100000000;
    struct Gragh{
        int cnt,x[N],y[N],nxt[N],fst[N];
        void set(){
            cnt=0;
            memset(fst,0,sizeof fst);
        }
        void add(int a,int b){
            x[++cnt]=a,y[cnt]=b;
            nxt[cnt]=fst[a],fst[a]=cnt;
        }
    }g,g2;
    int n,m,time,top,tot;
    int dfn[N],low[N],bh[N],st[N],w[N],v[N],dp[N],S,P;
    bool inst[N],vis[N],isp[N],fip[N];
    void Tarjan_Prepare(){
        time=top=tot=0;
        memset(bh,0,sizeof bh);
        memset(st,0,sizeof st);
        memset(dfn,0,sizeof dfn);
        memset(low,0,sizeof low);
        memset(vis,0,sizeof vis);
        memset(inst,0,sizeof inst);
    }
    void Tarjan(int x){
        dfn[x]=low[x]=++time;
        inst[x]=vis[x]=1;
        st[++top]=x;
        for (int i=g.fst[x];i;i=g.nxt[i])
            if (!vis[g.y[i]]){
                Tarjan(g.y[i]);
                low[x]=min(low[x],low[g.y[i]]);
            }
            else if (inst[g.y[i]])
                low[x]=min(low[x],low[g.y[i]]);
        if (dfn[x]==low[x]){
            tot++;
            bh[st[top]]=tot;
            inst[st[top]]=0;
            while (st[top--]!=x){
                bh[st[top]]=tot;
                inst[st[top]]=0;
            }
        }
    }
    int dfs(int x){
        if (dp[x]!=-Inf)
            return dp[x];
        dp[x]=fip[x]?v[x]:-Inf;
        for (int i=g2.fst[x];i;i=g2.nxt[i])
            dp[x]=max(dp[x],dfs(g2.y[i])+v[x]);
        return dp[x];
    }
    int main(){
        g.set();
        scanf("%d%d",&n,&m);
        for (int i=1,a,b;i<=m;i++){
            scanf("%d%d",&a,&b);
            g.add(a,b);
        }
        for (int i=1;i<=n;i++)
            scanf("%d",&w[i]);
        scanf("%d%d",&S,&P);
        memset(isp,0,sizeof isp);
        memset(fip,0,sizeof fip);
        memset(v,0,sizeof v);
        for (int i=1,pos;i<=P;i++){
            scanf("%d",&pos);
            isp[pos]=1;
        }
        Tarjan_Prepare();
        for (int i=1;i<=n;i++)
            if (!vis[i])
                Tarjan(i);
        g2.set();
        for (int i=1;i<=n;i++)
            v[bh[i]]+=w[i],fip[bh[i]]|=isp[i];
        for (int i=1;i<=g.cnt;i++)
            if (bh[g.x[i]]!=bh[g.y[i]])
                g2.add(bh[g.x[i]],bh[g.y[i]]);
        for (int i=1;i<=tot;i++)
            dp[i]=-Inf;
        printf("%d",dfs(bh[S]));
        return 0;
    }
  • 相关阅读:
    数据库范式
    RobotFrameWork自动化系列:安装配置
    jenkins安装
    jenkins+ant+ssh远程部署服务glassfish
    wordpress登录、修改、删除、查看代码记录
    wordpress 登录实例(一)
    BZOJ2806:[CTSC2012]Cheat(广义SAM,二分,DP)
    BZOJ4180:字符串计数(SAM,二分,矩阵乘法)
    BZOJ2780:[SPOJ8093]Sevenk Love Oimaster(广义SAM)
    BZOJ4032:[HEOI2015]最短不公共子串(SAM)
  • 原文地址:https://www.cnblogs.com/zhouzhendong/p/BZOJ1179.html
Copyright © 2011-2022 走看看