• 题解 P3387 【【模板】缩点】


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

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

    前置知识

    强联通分量

    拓扑排序

    没学过的同学可以学一下。

    分析

    我们可以先用强联通分量对图进行缩点,那么现在,这张图就是 DAGDAG 了。我们再拓扑排序,然后就去 dpdp

    dpdp 是这样的:

    我们用 fif_i 表示以第 ii 个点结尾的最优路径,这个显然很好转移。

    代码:

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    template<typename T>inline void read(T &FF){
    	T RR=1;FF=0;char CH=getchar();
    	for(;!isdigit(CH);CH=getchar())if(CH=='-')RR=-1;
    	for(;isdigit(CH);CH=getchar())FF=(FF<<1)+(FF<<3)+(CH^48);
    	FF*=RR;
    }
    template<typename T>inline void write(T x){
    	if(x<0)putchar('-'),x=-x;
    	if(x>9)write(x/10);
    	putchar('0'+x%10);
    }
    const int MAXN=1e6+10,MAXM=1e6+10;
    int s[MAXN],stop,dfn[MAXN],low[MAXN],scccnt,sccnum[MAXN],dfscnt,tot,he[MAXN],ne[MAXM<<1],ed[MAXM<<1],n,x,y,ds[MAXN],de[MAXN],m,dis[MAXN],tp,ans[MAXN],sum,f[MAXN];
    queue<int>q;
    vector<int>rd[MAXN];
    vector<int>cd[MAXN];
    void add(int x,int y){
    	ed[++tot]=y;
    	ne[tot]=he[x];
    	he[x]=tot;
    }
    void tuopu(){
    	for(int i=1;i<=scccnt;i++)
    		if(!de[i])q.push(i);
    	while(q.size()){
    		int u=q.front();
    		q.pop();
    		ans[++tp]=u;
    		for(auto i:cd[u])
    			if(--de[i]==0)q.push(i);
    	}
    }
    inline void tarjan(int now){
    	dfn[now]=low[now]=++dfscnt;
    	s[stop++]=now;
    	for(int i=he[now];i;i=ne[i]){
    		if(!dfn[ed[i]]){
    			tarjan(ed[i]);
    			low[now]=min(low[now],low[ed[i]]);
    		}else if(!sccnum[ed[i]]){
    			low[now]=min(low[now],dfn[ed[i]]);
    		}
    	}
    	if(dfn[now]==low[now]){
    		scccnt++;
    		do{
    			sccnum[s[--stop]]=scccnt;
    			ds[scccnt]+=dis[s[stop]];
    		}while(s[stop]!=now);
    	}
    }
    int main(){
    	read(n);read(m);
    	for(int i=1;i<=n;i++)read(dis[i]);
    	for(int i=1;i<=m;i++){
    		read(x);read(y);
    		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=he[i];j;j=ne[j])
    			if(sccnum[i]!=sccnum[ed[j]]){
    				de[sccnum[ed[j]]]++;
    				cd[sccnum[i]].push_back(sccnum[ed[j]]);
    				rd[sccnum[ed[j]]].push_back(sccnum[i]);
    			}
    	tuopu();
    	for(int i=1;i<=tp;i++){
            f[ans[i]]=ds[ans[i]];
            for(auto j:rd[ans[i]])
            	f[ans[i]]=max(f[ans[i]],f[j]+ds[ans[i]]);
        }
        for(int i=1;i<=scccnt;i++)sum=max(f[i],sum);
        cout<<sum;
    	return 0;
    }
    
  • 相关阅读:
    2019.04.24笔记
    转:浅谈SimpleDateFormat的线程安全问题
    H5和CSS
    Android Studio中 no module 问题,解决方法
    JS中,跨域调用(本地)另一个项目的方法
    IDEA中找不到spring的配置文件,或者不存在某个目录(比如没有src 目录)
    IDEA导入 Eclipse项目
    更新Android Studio,提示后直接点更新即可。gradle 两种更新方法,我用的第二种:手动添加gradle
    Android Studio的HAXM不支持虚拟机
    小米手机驱动程序安装教程
  • 原文地址:https://www.cnblogs.com/zhaohaikun/p/12816963.html
Copyright © 2020-2023  润新知