zoukankan      html  css  js  c++  java
  • 洛谷 P3387 【模板】缩点

    题目背景

    缩点+DP

    题目描述

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

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

    输入输出格式

    输入格式:

    第一行,n,m

    第二行,n个整数,依次代表点权

    第三至m+2行,每行两个整数u,v,表示u->v有一条有向边

    输出格式:

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

    输入输出样例

    输入样例#1:
    2 2
    1 1
    1 2
    2 1
    输出样例#1:
    2

    说明

    n<=10^4,m<=10^5,|点权|<=1000 算法:Tarjan缩点+DAGdp

    #include <cstdio>
    #include <vector>
    const int N = 1e5;
    using namespace std;
    vector<int>G[N],E[N];
    
    bool instack[N];
    int ans,Map[N/10][N/10],n,m,tim,Dq[N],dfn[N],low[N],stack[N],top,col[N],sumcol,f[N];
    int sec(int a,int b,int opt) {return opt?(a>b?a:b):(a>b?b:a);} 
    void tarjan(int x)
    {
        instack[x]=true;
        stack[++top]=x;
        low[x]=dfn[x]=++tim;
        for(int i=0;i<G[x].size();++i)
        {
            int v=G[x][i];
            if(!dfn[v])
            {
                tarjan(v);
                low[x]=sec(low[x],low[v],0);
            }
            else if(instack[v]) low[x]=sec(low[x],dfn[v],0);
        }
        if(low[x]==dfn[x])
        {
            sumcol++;
            int k;
            do
            {
                k=stack[top--];
                col[k]=sumcol;
                instack[k]=false;
                f[sumcol]+=Dq[k];
            }while(k!=x);
        }
    }
    void dfs(int x,int y)
    {
        ans=sec(ans,y,1);
        for(int i=0;i<E[x].size();++i)
            dfs(E[x][i],y+f[E[x][i]]);
        
    }
    int main()
    {
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;++i) scanf("%d",&Dq[i]);
        for(int u,v;m--;)
        {
            scanf("%d%d",&u,&v);
            G[u].push_back(v); 
        }
        for(int i=1;i<=n;++i) if(!dfn[i]) tarjan(i);
        for(int i=1;i<=n;++i)
        {
            for(int j=0;j<G[i].size();++j)
            {
                int v=G[i][j];
                if(col[i]!=col[v]&&!Map[col[i]][col[v]])
                {
                    Map[col[i]][col[v]]=1;
                    E[col[i]].push_back(col[v]); 
                }
            }
        }
        for(int i=1;i<=sumcol;++i) dfs(i,f[i]);
        printf("%d
    ",ans); 
        return 0;
    }
    我们都在命运之湖上荡舟划桨,波浪起伏着而我们无法逃脱孤航。但是假使我们迷失了方向,波浪将指引我们穿越另一天的曙光。
  • 相关阅读:
    2019 Multi-University Training Contest 1
    2019江西省省赛
    2019牛客暑期多校训练营 第二场
    母函数
    树形DP
    蓝桥杯-标题:打印图形
    蓝桥杯-标题:史丰收速算
    蓝桥杯-标题:切面条
    蓝桥杯-标题:李白打酒
    蓝桥杯-标题:啤酒和饮料
  • 原文地址:https://www.cnblogs.com/ruojisun/p/7423010.html
Copyright © 2011-2022 走看看