• BZOJ 1179: [Apio2009]Atm


    传送门

    解题思路

    今天这是咋了。。写了一堆假算法给了一堆假分。我竟然刚开始傻不拉几的写了个dijkstra跑最长路,结果87分???后面被告知只有spfa能跑最长路,并且需要将点权化为边权。。做法是因为所有atm都是非负数,所以不抢白不抢,我们考虑缩点。缩完点之后spfa最长路即可。多亏GhostCai神,要不得调几天估计。。。

    代码

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<queue>
    
    using namespace std;
    const int MAXN = 500005;
    
    inline int rd(){
        int x=0,f=1;char ch=getchar();
        while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
        while(isdigit(ch))  {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
        return x*f;
    }
    
    int n,m,a[MAXN],Val[MAXN];
    int head[MAXN],cnt,w[MAXN];
    int nxt[MAXN],to[MAXN];
    int nxt_[MAXN],to_[MAXN];
    int head_[MAXN],cnt_;
    int dfn[MAXN],low[MAXN];
    int dis[MAXN],col[MAXN],col_num;
    int stk[MAXN],top,num,st,ans;
    int S,P,xx[MAXN],yy[MAXN];
    bool vis[MAXN],b[MAXN],Bar[MAXN];
    
    inline void add(int bg,int ed){
        to[++cnt]=ed,nxt[cnt]=head[bg],head[bg]=cnt;
    }
    
    inline void add_(int bg,int ed,int v){
        to_[++cnt_]=ed,w[cnt_]=v,nxt_[cnt_]=head_[bg],head_[bg]=cnt_;
    }
    
    inline void tarjan(int x){
        dfn[x]=low[x]=++num;
        vis[x]=1;stk[++top]=x;
        for(register int i=head[x];i;i=nxt[i]){
            int u=to[i];
            if(!dfn[u]){
                tarjan(u);
                low[x]=min(low[x],low[u]);
            }
            else if(vis[u])
                low[x]=min(low[x],dfn[u]);
        }
        if(dfn[x]==low[x]){
            col[x]=++col_num;
            while(stk[top]!=x){
                vis[stk[top]]=0;
                col[stk[top--]]=col_num;
            }
            vis[x]=0;
            top--;
        }
    }
    
    inline void spfa(){
        memset(vis,false,sizeof(vis));
        queue<int> Q;
        Q.push(st);dis[st]=Val[st];vis[st]=1;
        while(!Q.empty()){
            int x=Q.front();Q.pop();
    //      cout<<x<<endl;      
            for(register int i=head_[x];i;i=nxt_[i]){
                int u=to_[i];
                if(dis[x]+w[i]>dis[u]){
                    dis[u]=dis[x]+w[i];
                    if(!vis[u]){
                        vis[u]=1;
                        Q.push(u);
                    }
                }
            }   vis[x]=0;
        }
    }
    
    int main(){
    //  freopen("2.in","r",stdin);
        n=rd();m=rd();
        for(register int i=1;i<=m;i++){
            int x=rd(),y=rd();
            xx[i]=x;yy[i]=y;
            add(x,y);
        }
        for(register int i=1;i<=n;i++) {a[i]=rd();if(!dfn[i]) tarjan(i);} 
    //  for(register int i=1;i<=n;i++) cout<<col[i]<<" ";
        S=rd();P=rd();
        for(register int i=1;i<=P;i++){
            int x=rd();
            b[x]=1;
        }
        for(register int i=1;i<=n;i++)
            Val[col[i]]+=a[i];
        for(register int i=1;i<=m;i++){
            int x=xx[i],y=yy[i];
            if(b[x]) Bar[col[x]]=1;
            if(b[y]) Bar[col[y]]=1;
            if(x==S) st=col[x];
            if(y==S) st=col[y];
            if(col[x]!=col[y]) add_(col[x],col[y],Val[col[y]]);
        }
    //  for(register int i=1;i<=col_num;i++)
    //      cout<<Bar[i]<<" "<<Val[i]<<endl;         
        spfa();
        for(register int i=1;i<=col_num;i++)
            if(Bar[i]) ans=max(ans,dis[i]);
        printf("%d",ans);
        return 0; 
    }
  • 相关阅读:
    洛谷 P4708
    NFLSOJ 1060
    Codeforces 1264D
    Solution -「多校联训」Sample
    Solution -「多校联训」光影交错
    Solution -「LOJ #138」「模板」类欧几里得算法
    Solution -「LOJ #141」回文子串 ||「模板」双向 PAM
    Codeforces Round #700 (Div. 2)
    Codeforces Round #698 (Div. 2) C and D
    「NOI 2021」题解
  • 原文地址:https://www.cnblogs.com/sdfzsyq/p/9676954.html
Copyright © 2020-2023  润新知