首页 > 其他分享 >CF1900E Transitive Graph

CF1900E Transitive Graph

时间:2023-12-05 16:33:23浏览次数:34  
标签:连通 int Graph 点权 ++ maxn low Transitive CF1900E

题目传送门

前置芝士:缩点拓扑排序

题目描述

有向图 \(G\) 有 \(N\) 个点,\(M\) 条边,点 \(u\) 的点权为 \(A_u\)。

若存在三元组 \(a,b,c\) 使得 \(a\) 至 \(b\) 有一条边,\(b\) 至 \(c\) 有一条边,则连一条 \(a\) 至 \(c\) 的边。重复执行以上操作,直到不存在这样的三元组为止。

求其最长链长度及最长链上的最小点权和。

分析

不难发现,只要 \(a,c\) 连通,则能连一条 \(a\) 至 \(c\) 的边。

若 \(a,c\) 在一个强连通分量内:

因为强连通分量内部任意两点连通,一个强连通分量在上述操作后可变为完全子图。

显然可以从任意一点进入子图遍历所有点后从任意一点离开子图。即一个完全子图的最长链长度为子图的点数。

点权和为完全子图内部的点权之和。

即对于强连通分量 \(G(V,E)\),最长链长度为 \(|V|\),点权和为 \(\sum\limits_{u\in V}a_u\)。

若 \(a,c\) 不在一个强连通分量内:

显然 \(a\to b,b\to c\) 的长度大于 \(a\to c\)。所以最优决策不是走 \(a\to c\) 这条新连的边。这里可视为不连接 \(a,c\)。

以每个点的强连通分量编号进行建图。

显然缩点后组成的图是 DAG。否则这个大图可以构成一个新的强连通分量。

接下来便可以拓扑排序后跑 DAG 上最长链板子。

设 \(f_u\) 为以 \(u\) 为起点的最长链长度,\(g_u\) 为以 \(u\) 为起点的最长链的最小点权和。

则有转移方程 \(f_u=\max\{f_u,f_v+w_v\},(u,v)\in E\)。

显然当 \(f_u<f_v+w_v\) 时,\(g_u=g_v+w'_v\)。

而当 \(f_u=f_v+w_v\) 时,\(g_u=\min\{g_u,g_v+w'_v\}\)。

代码

请欣赏工程码风。

#include <bits/stdc++.h>
#include <algorithm>
#define int long long
const int maxn = 2e5 + 20;
const int inf = 2e18;
int n, m;
int a[maxn];
int dfn[maxn], low[maxn], dfncnt;
int scc[maxn], sz[maxn], val[maxn], sccidx;
int stack[maxn], top;
int inDeg[maxn];
int f[maxn], fval[maxn];
std::vector <int> topo;
struct graph {
	struct edge {
		int u, v, w, next;
	};
	int head[maxn], cnt;
	edge e[maxn];
	void add(int x, int y) {
		e[++cnt].u = x, e[cnt].v = y, e[cnt].next = head[x], head[x] = cnt;
	}
} g, p;
void tarjan(int u, graph &g) {
	low[u] = dfn[u] = ++dfncnt;
	stack[++top] = u;
	for(int i = g.head[u]; i; i = g.e[i].next) {
		int v = g.e[i].v;
		if(!dfn[v]) tarjan(v, g), low[u] = std::min(low[u], low[v]);
		else if(!scc[v]) low[u]	= std::min(low[u], dfn[v]);
	}
	if(low[u] == dfn[u]) {
		sccidx++;
		while(stack[top] != u) scc[stack[top--]] = sccidx, sz[sccidx]++;
		scc[stack[top--]] = sccidx, sz[sccidx]++;
	}
}
void getSCC(int n, graph &g) {
	for(int i = 1; i <= n; i++)
		if(!dfn[i]) tarjan(i, g);
}
std::vector <int> topoSort(graph &g) {
	std::queue <int> q;
	std::vector <int> res;
	for(int i = 1; i <= sccidx; i++)
		if(inDeg[i] == 0) q.push(i);
	while(!q.empty()) {
		int u = q.front();
		q.pop();
		res.push_back(u);
		for(int i = g.head[u]; i; i = g.e[i].next) {
			int v = g.e[i].v, w = g.e[i].w;
			if(--inDeg[v] == 0) q.push(v);
		}
	}
	return res;
}
void solve() {
	int ans = 0, ansp;
	sccidx = 0, dfncnt = 0, g.cnt = 0, p.cnt = 0, top = 0;
	scanf("%lld %lld", &n, &m);
	for(int i = 1; i <= n; i++)
		scanf("%lld", &a[i]), g.head[i] = p.head[i] = val[i] = sz[i] = dfn[i] = scc[i] = 0;
	for(int i = 1; i <= m; i++) {
		int x, y;
		scanf("%lld %lld", &x, &y);
		g.add(x, y);
	}
	getSCC(n, g);
	for(int i = 1; i <= n; i++) {
		for(int j = g.head[i]; j; j = g.e[j].next) {
			int v = g.e[j].v;
			if(scc[i] == scc[v]) continue;
			p.add(scc[i], scc[v]);
			inDeg[scc[v]]++;
		}
	}
	for(int i = 1; i <= n; i++)
		val[scc[i]] += a[i];
	topo = topoSort(p);
	for(int i = 1; i <= sccidx; i++) {
		if(inDeg[i] == 0) fval[i] = val[i], f[i] = sz[i];
		else fval[i] = inf;
	}
	for(auto u : topo) {
		for(int i = p.head[u]; i; i = p.e[i].next) {
			int v = p.e[i].v, w = sz[v];
			if(f[v] < f[u] + w) f[v] = f[u] + w, fval[v] = fval[u] + val[v];
			else if(f[v] == f[u] + w) fval[v] = std::min(fval[v], fval[u] + val[v]);
		}
	}
	for(int i = 1; i <= n; i++)
		if(ans < f[i]) ans = f[i], ansp = fval[i];
		else if(ans == f[i]) ansp = std::min(ansp, fval[i]);
	printf("%lld %lld\n", ans, ansp);
}
signed main() {
	int t;
	scanf("%lld", &t);
	while(t--) solve();
	return 0;
}

标签:连通,int,Graph,点权,++,maxn,low,Transitive,CF1900E
From: https://www.cnblogs.com/CQWDX/p/17877572.html

相关文章

  • Detecting Unknown Encrypted Malicious Traffic in Real Time via Flow Interaction
    1前言1.1标题DetectingUnknownEncryptedMaliciousTrafficinRealTimeviaFlowInteractionGraphAnalysis1.2摘要为了保护网络的机密性和隐私性,目前互联网上的流量被广泛地加密。然而,流量加密技术经常被攻击者滥用,以掩盖其恶意行为。由于加密的恶意流量具有与良性......
  • cosmo 开源apollo Graphos 工具
    cosmo时候一个graphql联邦工具,可以用来方便的进行graphql协作参考架构说明wundergraph团队开源了不少graphql相关的工具了,cosmo是一个graphql联邦值得学习的工具参考资料https://cosmo-docs.wundergraph.com/https://github.com/wundergraph/cosmo......
  • Generative-Contrastive Graph Learning for Recommendation论文阅读笔记
    Abstract首先介绍了一下GCL的一些缺点,GCL是通过数据增强来构造对比视图,然后通过最大化对比视图之间的互信息来提供自监督信号。但是目前的数据增强技术都有着一定的缺点结构增强随机退出节点或边,容易破坏用户项目的内在本质特征增强对每个节点施加相同的尺度噪声增强,忽略的节......
  • 【graphviz笔记】
    入门新建sample.dot文件,打开编辑为:digraphg{xy}在命令行中输入dotsample.dot-Tpng-osample.png-T后接要生成的图片格式,可以是pdf、svg格式等。-o指明生成文件名指定节点属性digraphg{ 1[label="x",color=orange,style=filled] 2[label="y",col......
  • Vulkan/Graphics Pipelines
    渲染是vulkan最基础的功能,也是众多图形化应用最核心的部分。vulkan的渲染过程可以当作是通过执行不同阶段的命令以此来在展示设备上渲染出图片的过程。 vulkan中,渲染管线可以看作是一条生产流水线,命令在管线的开头进入,并且在管线内不同阶段执行。每个阶段都有诸如变换,读取命令......
  • 无涯教程-Python - 图形数据(Graph)
    CSGraph代表压缩稀疏图,其重点是基于稀疏矩阵表示的快速图算法。稀疏图图只是节点的集合,节点之间具有链接,图几乎可以代表任何事物-社交网络连接,其中每个节点都是一个人,并与熟人相连;图像,其中每个节点是一个像素,并连接到相邻像素;高维分布中的点,其中每个节点都连接到其最近的邻居,并......
  • 问题记录 <Latex 使用bibliography命令,引用文献中包含中文生僻字>
    问题描述LaTeX使用\bibliography和.bib设置参考文献时,中文生僻字无法显示。解决方式下载字体;将simsun.ttf文件放到.tex同一文件夹下;导言部分添加:%%解决生僻字问题,使用自定义命令\usepackage{ctex}\setCJKfamilyfont{myfont}{simsun.ttf}\newcommand{\MyFont}{\CJKfamil......
  • GraphFrames介绍和基本用法
    阅读本篇博客前需先了解图数据、scala、spark相关知识 GraphFrames是一款图处理类库。该类库构建在DataFrame之上,既能利用DataFrame良好的扩展性和强大的性能,同时也为Scala、Java和Python提供了统一的图处理API。github:https://github.com/graphframes/graphframes官方文档:h......
  • 8-1900E - Transitive Graph
    题意:思路:tarjan缩点后,对新图DAG进行拓扑dp。代码:点击查看代码#include<bits/stdc++.h>#defineintlonglongusingnamespacestd;constintN=1e6+7;constintinf=1e9+7;typedefpair<int,int>pll;intn,m;intdfn[N],low[N];intvis[N];vector<int>ve[N]......
  • [WARNING] The POM for com.alibaba:druid:jar:1.1.21 is invalid, transitive depend
    这个警告表明Maven在尝试下载或处理com.alibaba:druid:1.1.21这个依赖项时遇到了问题。警告的具体内容是说POM(ProjectObjectModel)文件无效,这可能会导致Maven无法正确地处理传递性依赖关系。有几种可能的原因和解决方法:1.网络问题:Maven可能无法从Maven仓库正确下载d......