zoukankan      html  css  js  c++  java
  • LUOGU P3387 【模板】缩点 (缩点+DAG dp)

    解题思路

    缩点后按拓扑排序跑一个dp。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<cstdlib>
    #include<queue>
    
    using namespace std;
    const int MAXN = 10005;
    const int MAXM = 100005;
    
    inline int rd(){
        int x=0,f=1;char ch=getchar();
        while(!isdigit(ch)) {f=ch=='-'?0:1;ch=getchar();}
        while(isdigit(ch))  {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
        return f?x:-x;
    }
    
    int n,m,head[MAXN],cnt,to[MAXM],nxt[MAXM],w[MAXN],wt[MAXN],ans;
    int head_[MAXN],cnt_,to_[MAXM],nxt_[MAXM],du[MAXN],f[MAXN];
    int dfn[MAXN],low[MAXN],num,stk[MAXN],top,col_num,col[MAXN];
    bool vis[MAXN];
    queue<int> Q;
    
    inline void add(int bg,int ed){
        to[++cnt]=ed,nxt[cnt]=head[bg],head[bg]=cnt;
    }
    void tarjan(int x){
        dfn[x]=low[x]=++num;
        stk[++top]=x;vis[x]=1;
        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(dfn[u],low[x]); 
        }
        if(low[x]!=dfn[x]) return;col_num++;
        while(stk[top]!=x) {
            wt[col_num]+=w[stk[top]];
            vis[stk[top]]=0;
            col[stk[top--]]=col_num;
        }top--;
        vis[x]=0;col[x]=col_num;wt[col_num]+=w[x];
    }
    
    inline void add_(int bg,int ed){
        to_[++cnt_]=ed,nxt_[cnt_]=head_[bg],head_[bg]=cnt_;
    }
    
    int main(){
        n=rd(),m=rd();int x,y,u;
        for(int i=1;i<=n;i++) w[i]=rd();
        for(int i=1;i<=m;i++){
            x=rd(),y=rd();
            add(x,y);
        }
        for(int i=1;i<=n;i++) if(!dfn[i]) tarjan(i);
        for(int i=1;i<=n;i++)
            for(int j=head[i];j;j=nxt[j]){
                u=to[j];
                if(col[u]!=col[i]) add_(col[i],col[u]),du[col[u]]++;
            }
        for(int i=1;i<=col_num;i++) if(!du[i]) Q.push(i),f[i]=wt[i];
        while(!Q.empty()){
            int x=Q.front();Q.pop();
            for(int i=head_[x];i;i=nxt_[i]){
                int u=to_[i];
                f[u]=max(f[u],f[x]+wt[u]);
                du[u]--;if(!du[u]) Q.push(u);
            }
        }
        for(int i=1;i<=col_num;i++) ans=max(ans,f[i]);
        printf("%d",ans);
        return 0;
    }
    View Code
  • 相关阅读:
    most-wanted-letter
    non-unique-elements
    python组建之paramiko的简介和简单使用
    Android平台使用termux,随时随地写代码
    发现生活中数学的美,然后记录下来
    别再用Microsoft Office,改为WPS或者Latex
    office2016 vol 中文版本
    Office 2016 英文版(VOL版)下载
    选择好用的生产力工具
    使用windows(win7和win10),最好用chocolatey
  • 原文地址:https://www.cnblogs.com/sdfzsyq/p/9755332.html
Copyright © 2011-2022 走看看