洛谷 P3387 【模板】缩点

news2024/12/27 5:41:26

【题目链接】

洛谷 P3387 【模板】缩点

【题目考点】

1. 图论:强连通分量,有向图缩点
2. 图论:拓扑排序 有向无环图动规

【解题思路】

已知所有顶点点权是非负的,要想求出点权加和最大的路径。
如果该路径经过一个顶点u,那么必然应该经过顶点u所在强连通分量中的所有顶点,这样可以使得点权加和最大。

如果一条路径从顶点u进入u所在的强连通分量,从顶点v离开该强连通分量,但没有经过该强连通分量中的顶点x。由于允许多次经过一条边或者一个点,那么完全可以从顶点v,走回顶点x,再走回顶点v,这样多经过一个顶点x,点权加和一定变得更大或与之前相等。

因此可以将每个强连通分量可以看作一个顶点,只要经过该连通分量,就必然要经过该强连通分量中的所有顶点,增加的点权为该强连通分量中所有顶点的点权加和。

首先使用求强连通分量的算法(Kosaraju算法或Tarjan算法),求出有向图中的所有强连通分量
而后进行缩点,缩点后一定会得到一个有向无环图。
原图为e,设一个新图g,新图g中每个顶点相当于原图e中的一个强连通分量,新图g中每个顶点的权值是该顶点对应原图e中的强连通分量中所有顶点权值的和。如果原图e中顶点u到顶点v有一条有向边,同时u、v不属于同一个强连通分量,那么在新图g中,u所属强连通分量对应的顶点 到 v所属强连通分量对应的顶点有一条有向边。这样得到的新图g中可能有重边,不过重边不影响拓扑排序算法。

而后使用拓扑排序求有向无环图,也就是缩点后的g图中点权加和最大的路径,具体方法见该题:
ybt 1262:【例9.6】挖地雷

【题解代码】

解法1:Tarjan算法求强连通分量 缩点
#include<bits/stdc++.h>
using namespace std;
#define N 10005
int n, m, a[N], ga[N], dp[N], degIn[N], ans; 
int dfn[N], low[N], ts, scc[N], sn;//scc[i]:顶点i所在的强连通分量 sn:强连通分量数量 
vector<int> edge[N], g[N];
bool inStk[N];
stack<int> stk;
void tarjan(int u)
{
	dfn[u] = low[u] = ++ts;
	stk.push(u);
	inStk[u] = true;
	for(int v : edge[u])
	{
		if(dfn[v] == 0)
		{
			tarjan(v);
			low[u] = min(low[u], low[v]);
		}
		else if(inStk[v])
			low[u] = min(low[u], dfn[v]);
	}
	if(dfn[u] == low[u])
	{
		int t;
		sn++;
		do
		{
			t = stk.top();
			scc[t] = sn;
			inStk[t] = false;
			stk.pop();
		} while(t != u);
	} 
}
void topoSort()
{
	queue<int> que;
	for(int v = 1; v <= sn; ++v) if(degIn[v] == 0)
	{ 
		dp[v] = ga[v]; 
		que.push(v);
	}
	while(!que.empty())
	{
		int u = que.front();
		que.pop();
		for(int v : g[u])
		{
			dp[v] = max(dp[v], dp[u]+ga[v]);
			if(--degIn[v] == 0)
				que.push(v);
		}
	}
}
int main()
{
	int u, v;
	cin >> n >> m;
	for(int i = 1; i <= n; ++i)
		cin >> a[i];
	for(int i = 1; i <= m; ++i)
	{
		cin >> u >> v;
		edge[u].push_back(v);
	}
	for(int i = 1; i <= n; ++i) if(dfn[i] == 0)
		tarjan(i);
	for(int u = 1; u <= n; ++u)
	{
		ga[scc[u]] += a[u];
		for(int v : edge[u]) if(scc[u] != scc[v])
		{
			g[scc[u]].push_back(scc[v]);//可能会产生重边,不影响拓扑排序 
			degIn[scc[v]]++;//degIn[i]:连通分量i的入度
		}
	}
	topoSort();
	for(int v = 1; v <= sn; ++v)
		ans = max(ans, dp[v]);
	cout << ans;
	return 0;
}
解法2:Kosaraju算法求强连通分量 缩点
#include<bits/stdc++.h>
using namespace std;
#define N 10005
int n, m, a[N], ga[N], dp[N], degIn[N], ans; 
int dfn[N], low[N], ts, scc[N], sn;//scc[i]:顶点i所在的强连通分量 sn:强连通分量数量 
vector<int> edge[N], rg[N], g[N];
bool vis[N];
stack<int> stk;
void dfs_rg(int u)
{
	vis[u] = true;
	for(int v : rg[u]) if(!vis[v])
		dfs_rg(v);
	stk.push(u);
}
void dfs_g(int u)
{
	vis[u] = true;
	scc[u] = sn;
	for(int v : edge[u]) if(!vis[v])
		dfs_g(v);
}
void kosaraju()
{
	for(int u = 1; u <= n; ++u)	if(!vis[u])
		dfs_rg(u);
	memset(vis, 0, sizeof(vis));
	while(!stk.empty())
	{
		int u = stk.top();
		stk.pop();
		if(!vis[u])
		{
			++sn;
			dfs_g(u);
		}
	}
}
void topoSort()
{
	queue<int> que;
	for(int v = 1; v <= sn; ++v) if(degIn[v] == 0)
	{ 
		dp[v] = ga[v]; 
		que.push(v);
	}
	while(!que.empty())
	{
		int u = que.front();
		que.pop();
		for(int v : g[u])
		{
			dp[v] = max(dp[v], dp[u]+ga[v]);
			if(--degIn[v] == 0)
				que.push(v);
		}
	}
}
int main()
{
	int u, v;
	cin >> n >> m;
	for(int i = 1; i <= n; ++i)
		cin >> a[i];
	for(int i = 1; i <= m; ++i)
	{
		cin >> u >> v;
		edge[u].push_back(v);
		rg[v].push_back(u);
	}
	kosaraju();
	for(int u = 1; u <= n; ++u)
	{
		ga[scc[u]] += a[u];
		for(int v : edge[u]) if(scc[u] != scc[v])
		{
			g[scc[u]].push_back(scc[v]);//可能会产生重边,不影响拓扑排序 
			degIn[scc[v]]++;//degIn[i]:连通分量i的入度
		}
	}
	topoSort();
	for(int v = 1; v <= sn; ++v)
		ans = max(ans, dp[v]);
	cout << ans;
	return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2266188.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

uniapp 微信小程序 数据空白展示组件

效果图 html <template><view class"nodata"><view class""><image class"nodataimg":src"$publicfun.locaAndHttp()?localUrl:$publicfun.httpUrlImg(httUrl)"mode"aspectFit"></image>&l…

12.26 学习卷积神经网路(CNN)

完全是基于下面这个博客来进行学习的&#xff0c;感谢&#xff01; ​​【深度学习基础】详解Pytorch搭建CNN卷积神经网络LeNet-5实现手写数字识别_pytorch cnn-CSDN博客 基于深度神经网络DNN实现的手写数字识别&#xff0c;将灰度图像转换后的二维数组展平到一维&#xff0c;…

【团标】《信息工程造价政务信息化项目造价评估方法》(TCQAE11021-2023)-费用标准解读系列33

《信息工程造价政务信息化项目造价评估方法》&#xff08;TCQAE11021-2023&#xff09;是中国电子质量管理协会2023年发布&#xff0c;2023年12月16日开始实施的标准&#xff08;了解更多可直接关注我们咨询&#xff09;。该标准适用于政务信息化项目的造价评估&#xff0c;政务…

mybatisplu设置自动填充

/*** mybatisplus的自动化填充*/public class JboltMetaObjectHandler implements MetaObjectHandler {Overridepublic void insertFill(MetaObject metaObject) {LocalDateTime now LocalDateTime.now(ZoneId.of("Asia/Shanghai"));this.strictInsertFill(metaObje…

音视频入门基础:MPEG2-TS专题(23)——通过FFprobe显示TS流每个packet的信息

一、引言 通过FFprobe命令&#xff1a; ffprobe -of json -show_packets XXX.ts 可以显示TS流/TS文件每个packet&#xff08;也称为数据包或多媒体包&#xff09;的信息&#xff1a; 对于TS流&#xff0c;上述的“packet”&#xff08;数据包或多媒体包&#xff09;是指&…

Linux电源管理——CPU Hotplug 流程

目录 一、相关概念 二、基本原理 三、代码分析 1、CPU_ON 2、CPU_OFF References Linux Version&#xff1a;linux-5.4.239 一、相关概念 在单核操作系统中&#xff0c;操作系统只需管理一个CPU&#xff0c;当系统有任务需要执行时&#xff0c;所有的任务会在该CPU的就绪…

探索数据的艺术:R语言与Origin的完美结合

探索数据的艺术&#xff1a;R语言与Origin的完美结合 R语言统计分析与可视化从入门到精通内容简介获取方式 Origin绘图深度解析&#xff1a;科研数据的可视化艺术内容简介获取方式 R语言统计分析与可视化从入门到精通 内容简介 本书循序渐进、深入讲解了R语言数据统计分析与应…

python基础训练之元组的基本操作

主页包含元组基础知识点 【练习要求】 针对于元组的知识点进行常用的创建、定义、查询元素、查看元组长度等操作。效果实现如下 (注&#xff1a;特别要注意一下切片的用法) #创建元组的两种方法 T1 () T2 tuple() #定义一个元组并存储数据张三, 李四, 王五 T3 (张三, 李四…

选煤厂可视化技术助力智能化运营

通过图扑 HT 可视化搭建智慧选煤厂管理平台&#xff0c;优化了选煤生产流程&#xff0c;提高了资源利用率和安全性&#xff0c;助力企业实现智能化运营和可持续发展目标。

C语言基础:指针(数组指针与指针数组)

数组指针与指针数组 数组指针 概念&#xff1a;数组指针是指向数组的指针&#xff0c;本质上还是指针 特点&#xff1a; 先有数组&#xff0c;后有指针 它指向的是一个完整的数组 一维数组指针&#xff1a; 语法&#xff1a; 数据类型 (*指针变量名)[行容量][列容量]; 案…

接口测试Day03-postman断言关联

postman常用断言 注意&#xff1a;不需要手敲&#xff0c;点击自动生成 断言响应状态码 Status code&#xff1a;Code is 200 //断言响应状态码为 200 pm.test("Status code is 200", function () {pm.response.to.have.status(200); });pm: postman的实例 test() …

01- 三自由度串联机械臂位置分析

三自由度串联机械臂如下图所示&#xff08;d180mm&#xff0c;L1100mm&#xff0c;L280mm&#xff09;&#xff0c;利用改进DH法建模&#xff0c;坐标系如下所示&#xff1a; 利用改进DH法建模&#xff0c;该机器人的DH参数表如下所示&#xff1a; 对该机械臂进行位置分析&…

lxml 解析xml\html

from lxml import etree# XML文档示例 xml_doc """ <root><book><title>Python编程指南</title><author>张三</author></book><book><title>Python高级编程</title><author>李四</autho…

用Python写炸金花游戏

文章目录 **代码分解与讲解**1. **扑克牌的生成与洗牌**2. **给玩家发牌**3. **打印玩家的手牌**4. **定义牌的优先级**5. **判断牌型**6. **确定牌型优先级**7. **比较两手牌的大小**8. **计算每个玩家的牌型并找出赢家**9. **打印结果** 完整代码 以下游戏规则&#xff1a; 那…

基于 SpringBoot微信小程序的医院预约挂号系统

摘 要 时代在飞速进步&#xff0c;每个行业都在努力发展现在先进技术&#xff0c;通过这些先进的技术来提高自己的水平和优势&#xff0c;医院预约挂号系统当然不能排除在外。医院预约挂号系统是在实际应用和软件工程的开发原理之上&#xff0c;运用微信开发者、java语言以及…

高仿CSDN编辑器,前端博客模板

高仿CSDN编辑器纯前端模板&#xff0c;使用的js、html、vue、axios等技术&#xff0c;网络请求库已进行封装&#xff0c;可以按需调整界面,需要源码联系(4k左右)。 1.支持代码高亮 2.支持目录点击定位 3.支持文件上传、图片上传&#xff08;需要自己写后端接口&#xff09; 4.M…

【C++11】类型分类、引用折叠、完美转发

目录 一、类型分类 二、引用折叠 三、完美转发 一、类型分类 C11以后&#xff0c;进一步对类型进行了划分&#xff0c;右值被划分纯右值(pure value&#xff0c;简称prvalue)和将亡值 (expiring value&#xff0c;简称xvalue)。 纯右值是指那些字面值常量或求值结果相当于…

在线oj项目 Ubuntu安装vue/cil(vue脚手架)

参考:https://blog.csdn.net/weixin_66062303/article/details/129046198 笔记 参考:https://blog.csdn.net/m0_74352571/article/details/144076227 https://cli.vuejs.org/zh/guide/installation.html 确保nodejs已经安装 npm换源淘宝镜像&#xff08;可以不操作或者使用魔…

Python字符串及正则表达式(十一):正则表达式、使用re模块实现正则表达式操作

前言&#xff1a;在 Python 编程的广阔天地中&#xff0c;字符串处理无疑是一项基础而关键的技能。正则表达式&#xff0c;作为处理字符串的强大工具&#xff0c;以其灵活的模式匹配能力&#xff0c;在文本搜索、数据清洗、格式验证等领域发挥着不可替代的作用。本系列博客已经…

项目37:简易个人健身记录器 --- 《跟着小王学Python·新手》

项目37&#xff1a;简易个人健身记录器 — 《跟着小王学Python新手》 《跟着小王学Python》 是一套精心设计的Python学习教程&#xff0c;适合各个层次的学习者。本教程从基础语法入手&#xff0c;逐步深入到高级应用&#xff0c;以实例驱动的方式&#xff0c;帮助学习者逐步掌…