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<map>
    #include<queue>
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #define MAXN 100010
    using namespace std;
    queue<int>que;
    map<int,int>ma[MAXN];
    int n,m;
    int sumcol,ans;
    int tot,tot1,tim,top;
    int col[MAXN],into[MAXN];
    int val[MAXN],cost[MAXN],dis[MAXN];
    int to[MAXN],net[MAXN],head[MAXN];
    int to1[MAXN],net1[MAXN],head1[MAXN];
    int low[MAXN],dfn[MAXN],vis[MAXN],stack[MAXN],visstack[MAXN];
    void add(int u,int v){
        to[++tot]=v;net[tot]=head[u];head[u]=tot;
    }
    void add1(int u,int v){
        to1[++tot1]=v;net1[tot1]=head1[u];head1[u]=tot1;
    }
    void tarjin(int now){
        stack[++top]=now;
        low[now]=dfn[now]=++tim;
        vis[now]=1;
        visstack[now]=1;
        for(int i=head[now];i;i=net[i])
            if(visstack[to[i]])
                low[now]=min(low[now],dfn[to[i]]);
            else if(!vis[to[i]]){
                tarjin(to[i]);
                low[now]=min(low[now],low[to[i]]);
            }
        if(dfn[now]==low[now]){
            sumcol++;
            col[now]=sumcol;
            while(stack[top]!=now){
                col[stack[top]]=sumcol;
                visstack[stack[top]]=0;
                top--;
            }
            visstack[now]=0;
            top--;
        }
    }
    void spfa(int s){
        memset(dis,0,sizeof(dis));
        memset(vis,0,sizeof(vis));
        while(!que.empty())    que.pop();
        dis[s]=cost[s];
        vis[s]=1;
        que.push(s);
        while(!que.empty()){
            int now=que.front();
            que.pop();
            vis[now]=0;
            for(int i=head1[now];i;i=net1[i])
                if(dis[to1[i]]<dis[now]+cost[to1[i]]){
                    dis[to1[i]]=dis[now]+cost[to1[i]];
                    if(!vis[to1[i]]){
                        vis[to1[i]]=1;
                        que.push(to1[i]);
                    }
                }
        }
        for(int i=1;i<=sumcol;i++)    ans=max(ans,dis[i]);
    }
    int main(){
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++)    scanf("%d",&val[i]);
        for(int i=1;i<=m;i++){
            int u,v;
            scanf("%d%d",&u,&v);
            add(u,v);
        }
        for(int i=1;i<=n;i++)
            if(!vis[i])
                tarjin(i);
        for(int i=1;i<=n;i++)
            for(int j=head[i];j;j=net[j])
                if(col[i]!=col[to[j]])
                    if(ma[col[i]].find(col[to[j]])==ma[col[i]].end()){
                        ma[col[i]][col[to[j]]]=1;
                        into[col[to[j]]]++;
                        add1(col[i],col[to[j]]);
                    }
        for(int i=1;i<=n;i++)    cost[col[i]]+=val[i];
        for(int i=1;i<=sumcol;i++)
            if(!into[i])
                spfa(i);
        cout<<ans;
    }
    细雨斜风作晓寒。淡烟疏柳媚晴滩。入淮清洛渐漫漫。 雪沫乳花浮午盏,蓼茸蒿笋试春盘。人间有味是清欢。
  • 相关阅读:
    Java泛型T与?
    json解析出现:java.lang.ClassCastException: net.sf.ezmorph.bean.MorphDynaBean cannot be cast to XXX
    Html 项目使用自定义字体文件问题
    修复 WordPress 通过邮箱 找回密码时的链接无效&新用户注册时提示的链接无效
    Linux查询进程和结束进程
    Linux --- 程序后台运行的几种方法
    bash_profile和bashsrc的区别
    在CentOS中安装与配置Server JRE 8
    JRE和JDK的区别
    java中静态代码块详解
  • 原文地址:https://www.cnblogs.com/cangT-Tlan/p/7794928.html
Copyright © 2011-2022 走看看