• [APIO2009]抢掠计划 解题报告


    这道题码的十分痛苦。

    题目链接

    思路:tarjan缩点,重新建图,点权转边权,边权变为负值,跑一遍spfa求最长路即可。

    思路很简单,但是码量有点痛苦,打了一百行,打两个板子就发现了许多问题,例如:程序出错的时候不知道是哪里出了问题,找错十分麻烦。我自己出现的错误还是挺多的,模板不是很熟悉。

    代码:

    #include<cstdio>
    #include<iostream>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    using namespace std;
    const int N=500009;
    struct Edge{
        int next,to,dis;
    }e[N],E[N];
    int n,m,num,NUM,s,p,co,top,cnt,l,r;
    int head[N],far[N],HEAD[N],ans=0x3f3f3f3f,q[3*N],atm[N],flag[N],pd[N],val[N],stk[N],low[N],dfn[N],col[N],vis[N];
    void add(int u,int v){
        e[++num].to=v;
        e[num].next=head[u];
        head[u]=num;
    }
    void ADD(int u,int v,int w){
        E[++NUM].to=v;
        E[NUM].dis=w;
        E[NUM].next=HEAD[u];
        HEAD[u]=NUM;
    }
    void tarjan(int u){
        low[u]=dfn[u]=++cnt;
        stk[++top]=u;
        vis[u]=1;
            for(int i=head[u];i;i=e[i].next){
                int v=e[i].to;
                if(!dfn[v]){
                    tarjan(v);
                    low[u]=min(low[u],low[v]);
                }
                else
                if(vis[v]){
                    low[u]=min(low[u],dfn[v]);
                }
            }
        if(low[u]==dfn[u]){
            col[u]=++co;
            vis[u]=0;
            val[co]+=atm[u];
            while(stk[top]!=u){
                col[stk[top]]=co;
                val[co]+=atm[stk[top]];
                vis[stk[top]]=0;
                top--;
            }
            top--;
        }
    }
    void spfa(){
        l=0;r=1;
        for(int i=1;i<=co;i++)
        far[i]=0x3f3f3f3f;
        q[1]=col[s];
        far[col[s]]=-val[col[s]];
        while(l<=r){
        l++;
        int now=q[l];
        pd[now]=0;
        for(int i=HEAD[now];i;i=E[i].next){
            int v=E[i].to;
            if(far[now]+E[i].dis<far[v]){
                far[v]=far[now]+E[i].dis;
                if(!pd[v]){
                r++;
                pd[v]=1;
                q[r]=v;
                }
                }
            }
        }
    }
    int main(){
        scanf("%d%d",&n,&m);
        for(int i=1;i<=m;i++){
            int u,v;
            scanf("%d%d",&u,&v);
            add(u,v);
        }
        for(int i=1;i<=n;i++)
        scanf("%d",&atm[i]);
        scanf("%d%d",&s,&p);
        for(int i=1;i<=p;i++){
            int k;
            scanf("%d",&k);
            flag[k]=1;
        }
        for(register int i=1;i<=n;i++)
        if(!dfn[i])tarjan(i);
        for(register int u=1;u<=n;u++)
        for(int i=head[u];i;i=e[i].next){
            int v=e[i].to;
            if(col[v]!=col[u])
            ADD(col[u],col[v],-val[col[v]]);
        }
        spfa();
        for(int i=1;i<=n;i++)
        if(flag[i]&&ans>far[col[i]])
        ans=far[col[i]];
        printf("%d",-ans);
        return 0;
    }

    以前只做过 tarjan+树型dp的,这道题是tarjan + spfa 的。

  • 相关阅读:
    Android2.3.7源码结构分析
    【开源推荐】AllJoyn:打造全球物联网的通用开源框架
    Ubuntu12.04安装JDK6
    ubuntu12.04升级后找不到共享目录
    Windows Embedded Compact 7新特性
    Windows Embedded Compact 2013 安装体验
    Windows CE,你妈吗喊你在多核上玩玩
    April Fools Contest 2017 C
    April Fools Contest 2017 B
    April Fools Contest 2017 A
  • 原文地址:https://www.cnblogs.com/sky-zxz/p/9669921.html
Copyright © 2020-2023  润新知