zoukankan      html  css  js  c++  java
  • 洛谷3387:【模板】缩点——题解

    https://www.luogu.org/problemnew/show/P3387

    给定一个n个点m条边有向图,每个点有一个权值,求一条路径,使路径经过的点权值之和最大。你只需要求出这个权值和。

    允许多次经过一条边或者一个点,但是,重复经过的点,权值只计算一次。

    有环我们很不好判断,但是显然在一个强连通分量里面的点我们都可以到达。

    所以缩起来之后就是一个DAG,之后随便你怎么算都行(bfs/dfs)

    (我觉得并不算是dp emmm)

    #include<stack>
    #include<queue>
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    using namespace std;
    typedef long long ll;
    const int N=1e4+5;
    const int M=1e5+5;
    inline int read(){
        int x=0,w=1;char ch=0;
        while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
        return x*w;
    }
    struct node{
        int w,to,nxt;
    }e[2][M];
    int cnt,h[2][N];
    inline void add(int u,int v,int k){
        e[k][++cnt].to=v;e[k][cnt].nxt=h[k][u];h[k][u]=cnt;
    }
    int dfn[N],low[N],val[N],to[N],sum[N],f[N],indeg[N],t,l;
    stack<int>q;
    queue<int>p;
    bool inq[N],vis[N];
    void tarjan(int u){
        int v;
        dfn[u]=low[u]=++t;
        q.push(u);inq[u]=1;
        for(int i=h[0][u];i;i=e[0][i].nxt){
        v=e[0][i].to;
        if(!dfn[v]){
            tarjan(v);
            low[u]=min(low[u],low[v]);
        }else if(inq[v]){
            low[u]=min(low[u],dfn[v]);
        }
        }
        if(dfn[u]==low[u]){
        l++;
        do{
            v=q.top();
            q.pop();
            inq[v]=0;
            to[v]=l;
            sum[l]+=val[v];
        }while(v!=u);
        }
    }
    void bfs(int u){
        vis[u]=1;f[u]=sum[u];
        p.push(u);
        while(!p.empty()){
        u=p.front();p.pop();vis[u]=0;
        for(int i=h[1][u];i;i=e[1][i].nxt){
            int v=e[1][i].to;
            if(f[v]<f[u]+sum[v]){
            f[v]=f[u]+sum[v];
            if(!vis[v]){
                vis[v]=1;
                p.push(v);
            }
            }
        }
        }
    }
    int main(){
        int n=read(),m=read();
        for(int i=1;i<=n;i++)val[i]=read();
        for(int i=1;i<=m;i++){
        int u=read(),v=read();
        add(u,v,0);
        }
        for(int i=1;i<=n;i++){
        if(!dfn[i])tarjan(i);
        }
        for(int u=1;u<=n;u++){
        for(int j=h[0][u];j;j=e[0][j].nxt){
            int v=to[e[0][j].to];
            bool link=0;
            for(int k=h[1][to[u]];k&&!link;k=e[1][k].nxt){
            int w=e[1][k].to;
            if(v==w)link=1;
            }
            if(!link&&to[u]!=v){
            add(to[u],v,1);
            indeg[v]++;
            }
        }
        }
        memset(f,-127,sizeof(f));
        for(int i=1;i<=l;i++){
        if(!indeg[i]){
            bfs(i);
        }
        }
        int ans=0;
        for(int i=1;i<=l;i++)ans=max(ans,f[i]);
        printf("%d
    ",ans);
        return 0;
    }

    +++++++++++++++++++++++++++++++++++++++++++

    +本文作者:luyouqi233。               +

    +欢迎访问我的博客:http://www.cnblogs.com/luyouqi233/+

    +++++++++++++++++++++++++++++++++++++++++++

  • 相关阅读:
    设计模式-外观模式
    多线程面试笔试题-1
    final 关键字
    java 继承 初始化顺序
    java内部类
    Python-面向对象-静态方法
    接口自动化测试框架搭建
    使用yaml设计测试用例进行单接口测试
    数据驱动测试--对excel文件的操作
    TCP协议详解
  • 原文地址:https://www.cnblogs.com/luyouqi233/p/8696626.html
Copyright © 2011-2022 走看看