zoukankan      html  css  js  c++  java
  • luoguP3387 【模板】缩点

    www.cnblogs.com/shaokele/


    luoguP3387 【模板】缩点##

      Time Limit: 1 Sec
      Memory Limit: 128 MB

    Description###

      给定一个n个点m条边有向图,每个点有一个权值,求一条路径,使路径经过的点权值之和最大。你只需要求出这个权值和。
      允许多次经过一条边或者一个点,但是,重复经过的点,权值只计算一次。
     

    Input###

      第一行,n,m
      
      第二行,n个整数,依次代表点权
      
      第三至m+2行,每行两个整数u,v,表示u->v有一条有向边
     

    Output###

      共一行,最大的点权之和。
     

    Sample Input###

      2 2
      
      1 1
      
      1 2
      
      2 1
     

    Sample Output###

      2
      

    HINT###

      n<=104,m<=105,点权<=1000
      
      算法:Tarjan缩点+DAGdp

    题目地址:  luoguP3387 【模板】缩点

    题目大意: 模板题

    题解:

      Tarjan缩点模板题


    AC代码

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    const int N=1e4+5,M=1e5+5;
    int n,m,num,top,tot,ans,cnt1,cnt2;
    int a[N],dfn[N],low[N],s[N],sum[N],col[N],f[N],in[N];
    int last1[N],last2[N];
    bool ins[N];
    int read(){
        int x=0,f=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
        return x*f;
    }
    struct edge1{
        int to,next;
    }e1[M<<1];
    struct edge2{
        int to,next;
    }e2[M<<1];
    void add_edge1(int u,int v){
        e1[++cnt1]=(edge1){v,last1[u]};last1[u]=cnt1;
    }
    void add_edge2(int u,int v){
        e2[++cnt2]=(edge2){v,last2[u]};last2[u]=cnt2;
    }
    void Tarjan(int u){
        dfn[u]=low[u]=++tot;
        s[++top]=u;ins[u]=1;
        for(int i=last1[u];i;i=e1[i].next){
            int v=e1[i].to;
            if(!dfn[v]){
                Tarjan(v);
                low[u]=min(low[u],low[v]);
            }else if(ins[v])
                low[u]=min(low[u],dfn[v]);
        }
        if(dfn[u]==low[u]){
            num++;
            while(s[top]!=u){
                sum[num]+=a[s[top]];
                col[s[top]]=num;
                ins[s[top--]]=0;
            }
            sum[num]+=a[s[top]];
            col[s[top]]=num;
            ins[s[top--]]=0;
        }
    }
    void dp(int u,int fa){
        f[u]=sum[u];
        for(int i=last2[u];i;i=e2[i].next){
            int v=e2[i].to;
            if(v==fa)continue;
            dp(v,u);
            f[u]=max(f[u],f[v]+sum[u]);
        }
    }
    int main(){
        n=read();m=read();
        for(int i=1;i<=n;i++)a[i]=read();
        for(int i=1;i<=m;i++){
            int u=read(),v=read();
            add_edge1(u,v);
        }
        for(int i=1;i<=n;i++)
            if(dfn[i]==0)Tarjan(i);
        for(int u=1;u<=n;u++)
            for(int i=last1[u];i;i=e1[i].next){
                int v=e1[i].to;
                if(col[u]!=col[v]){
                    add_edge2(col[u],col[v]);
                    in[col[v]]++;
                }
            }
        for(int i=1;i<=num;i++)
            if(in[i]==0){
                dp(i,0);
                ans=max(ans,f[i]);
            }
        printf("%d
    ",ans);
        return 0;
    }
    
  • 相关阅读:
    antd4.0 踩坑记录
    使用movable-view制作可拖拽的微信小程序弹出层效果。
    Taro踩坑记录一: swiper组件pagestate定制,swiperChange中setState导致组件不能滚动。
    Failed to load resource: net::ERR_INSECURE_RESPONSE 问题解决记录
    Vue-cli中使用vConsole,以及设置JS连续点击控制vConsole按钮显隐功能实现
    dvajs+antd定制主题踩坑记录
    关于iosselectjs插件设置同步值的操作实践
    《你不知道的javascript》上卷笔记整理(一)
    三次面试总结以及今后的todolist
    前端Vue中常用rules校验规则
  • 原文地址:https://www.cnblogs.com/shaokele/p/9354713.html
Copyright © 2011-2022 走看看