CF1515G

news/2024/9/29 7:21:58

CF1515G Phoenix and Odometers

首先进行缩点,对于一个点,与它不在同一连通分量的点无法形成回路,所以对每个连通分量分别计算。

假设一个点 \(u\),有两个长度为 \(a\)\(b\) 的环,那么就相当于找两个非负整数 \(x\)\(y\),使得 \(ax+by=w\),其中 \(w\) 为题中的路径长,根据裴蜀定理得到上述方程成立当且仅当 \(\gcd(a,b)\mid w\)

考虑如何求出 \(\gcd(a,b)\),即点 \(u\) 所有环长的 gcd。

首先在强连通分量中存在四种边:树边、横叉边、返祖边、前向边。

举个例子:

image

假设根节点为 \(1\),根节点通过树边到节点 \(u\) 的路径长度为 \(dis_{u}\)

以横叉边 \(5\to 3\) 这条边为例,设它的边权为 \(w\)。因为这些点在同一连通分量且它是横叉边,说明 \(3\) 这边已经可以形成回到 \(1\) 的一条回路了。

所以其中一条回路为 \(1\) 通过树边连向 \(3\)\(3\) 再通过一些非树边连回 \(1\),大体路径为 \(1\to 3\to 1\),长度可以表示为 \(dis_{3}+val(3,1)\)

又因为当前的横叉边 \(5\to 3\),产生了一条新的回路。

\(1\) 通过树边连向 \(5\)\(5\) 通过横叉边连向 \(3\)\(3\) 通过一些非树边连回 \(1\),大体路径为 \(1\to 5\to 3\to 1\),长度为 \(dis_{5}+w+val(3,1)\)

这两条回路的 gcd,可以使用辗转相减进行化简,将公共路径部分减掉,则 gcd 为 \(\gcd(dis_{3}+val(3,1),dis_{5}+w-dis_{3})\)

这样对于一条横叉边 \(u\to v\),对 gcd 产生的贡献为 \(dis_{u}+w-dis_{v}\)

然后通过分析发现,返祖边和前向边对 gcd 的贡献也是 \(dis_{u}+w-dis_{v}\),即所有的非树边,对答案的贡献是相同的。

求出所有环长的 gcd,设为 \(g\),然后根据题意得出 \(a\times g+s=b\times t\),再一次使用裴蜀定理得到 \(\gcd(g,t)\mid s\)

#include<bits/stdc++.h>
using namespace std;
#define int long long
int n,m,q;
const int maxn=2e5+10;
struct node{int to,nxt,w;
};
node e[maxn];
int head[maxn],tot;
void add(int u,int v,int w){++tot;e[tot].to=v;e[tot].nxt=head[u];e[tot].w=w;head[u]=tot;
}
int dfn[maxn],low[maxn],st[maxn];
bool vis[maxn];
int scc[maxn];
int res,tp,cnt;
void tarjan(int u){dfn[u]=low[u]=++res;st[++tp]=u;vis[u]=1;for(int i=head[u];i!=0;i=e[i].nxt){int v=e[i].to;if(!dfn[v]){tarjan(v);low[u]=min(low[u],low[v]);}else if(vis[v]){low[u]=min(low[u],dfn[v]);}}if(dfn[u]==low[u]){++cnt;while(st[tp]!=u){scc[st[tp]]=cnt;vis[st[tp]]=0;--tp;}scc[st[tp]]=cnt;vis[st[tp]]=0;--tp;}
}
int dis[maxn],g[maxn];
bool tag[maxn];
void dfs(int u,int cur){tag[u]=1;for(int i=head[u];i!=0;i=e[i].nxt){int v=e[i].to;int w=e[i].w;if(scc[v]!=cur){continue;}if(tag[v]){g[cur]=__gcd(g[cur],dis[u]-dis[v]+w);continue;}dis[v]=dis[u]+w;dfs(v,cur);}
}
signed main(){scanf("%lld%lld",&n,&m);for(int i=1;i<=m;i++){int u,v,w;scanf("%lld%lld%lld",&u,&v,&w);add(u,v,w);}for(int i=1;i<=n;i++){if(!dfn[i]){tarjan(i);}}for(int i=1;i<=n;i++){if(!tag[i]){dfs(i,scc[i]);}}scanf("%lld",&q);while(q--){int u,s,t;scanf("%lld%lld%lld",&u,&s,&t);if(s%__gcd(g[scc[u]],t)==0){printf("YES\n");}else{printf("NO\n");}}return 0;
}

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

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

相关文章

模拟集成电路设计系列博客——7.1.3 电阻电容混合SAR ADC

7.1.3 电阻电容混合SAR ADC 在DAC中组合使用电阻串和电容阵列的方式同样可以在ADC中使用,一种实现[Fotouhi, 1979]如下图所示:第一步是将所有的电容都充电到\(V_{in}\)并重置比较器,接着,通过逐次逼近的方式来查找两个相邻的电阻节点具有大于和小于\(V_{in}\)的电压。使用两…

VR-LLM-AAC

VR-LLM-AAC 方案测试 测试一:汉字聚类hanzi_similar 算法 GithubKmeans 算法hanzi_similar 通过四角编码,汉字结构,偏旁部首,笔画数来判断两个汉字之间的相似度 将权重调整为调高偏旁部首和汉字结构的权重 根据任意两个汉字之间的相似度,通过 Kmeans 算法构建相似度矩阵,…

组件/框架设计原则

Windows应用软件开发,会有很多常用的模块,比如数据库、配置文件、日志、后台通信、进程通信、埋点、浏览器等等。下面是目前我们公司windows梳理的部分组件,梳理出来方便大家了解组件概念以及依赖关系:每个应用里,现在或者以后都可能会存在这些模块。以我团队开发的全家桶…

会计科目大白话

会计科目大白话,这样更好理解

Android中EventBus简单使用

综述 消息总线又叫事件总线, 被广泛的应用于各类项目之中. 但是此处只概述Android体系中用到的框架. 为什么项目会需要一个消息总线呢? 一句话概括, 在大多数常见项目中, 随着项目变大, 项目可能出现大量的跨页面, 跨组件, 跨线程, 跨进程来传递消息与数据的需求. 为了更方便的…

记录--N 个值得一看的前端代码片段

🧑‍💻 写在开头 点赞 + 收藏 === 学会🤣🤣🤣在日常的开发过程中,我们都会有一些常用的代码片段,这些代码片段可以直接复制到各个项目中使用,非常方便。如果你有接手过别人的项目,就可以很明显感受到几个项目一般都会有一些相同的工具类方法,这些方法就是之前开…

2024.06 PET父母效能【扩大无问题区】

参考:https://www.jianshu.com/p/1676653be220 PART1:父母也是一个平凡的人,做真实的父母 关注关系,而非问题 父母不需要为每个问题负责 PART2:孩子有问题:积极的倾听,门把手法,让孩子自己发现问题,解决问题接纳孩子,更要接纳自己PART3:父母有问题:面质技巧 1.清楚界…

2024.06PET父母效能

参考:https://www.jianshu.com/p/1676653be220 PART1:父母也是一个平凡的人,做真实的父母 关注关系,而非问题 父母不需要为每个问题负责 PART2:孩子有问题:积极的倾听,门把手法,让孩子自己发现问题,解决问题接纳孩子,更要接纳自己PART3:父母有问题:面质技巧 1.清楚界…