题解:[ARC144E] GCD of Path Weights

前言

挺有意思的题。

从某些特殊角度来理解的话,也不算不可做题。

思路分析

首先要点权转边权,我们对于一个点 \(x\),拆点 \(x,x'\),连边 \(x\to x'\),边权为 \(a_x\),对于原图上的边 \((x,y)\),连边 \(x'\to y\),边权为 \(0\)

然后我们要考虑 \(1\to n\) 的路径上边权和的 \(\gcd\)

然后有一个很有意思的结论:

DAG 上 \(1\to n\) 的路径的边权和是 \(k\) 的倍数,当且仅当存在序列 \(e\),满足原图上的边 \((x,y,w)\) \(e_x+w\bmod k=e_y\)

其中,\(e\) 被称为势能。

也很好感性理解,我们对于任意一条路径,比如 \(1\to x\to y\to n\),如果我们想要用 \((x,y,w)\) 来替换 \(x\to y\) 的部分,那么需要保证替换完点的势能不变,不然会出问题。

于是我们可以在 dfs 的过程中求出 \(k\) 的最大值。

在实现上,因为势能是双向的,所以我们需要对于每一条边建反边,同时边权也要相反。同时如果一个点不在 \(1\to n\) 的路径上,我们直接把它删了就行。

注意因为 \(a_x=-1\) 时点权可以随意指定,所以 \(e_x\)\(e_x'\) 之间没有关系,想要是多少就是多少,我们不连 \(x\to x'\) 的边就行了。

复杂度 \(O(n \log v)\)

代码实现

#include<bits/stdc++.h>
#define int long long
using namespace std;
int n,m,x,y,ans,a[600005];
vector<int> v[600005],t[600005];
int head[600005],nxt[12000005],targetx[12000005],targetw[12000005],tot;
void add(int x,int y,int w){
	tot++;
	nxt[tot]=head[x];
	head[x]=tot;
	targetx[tot]=y;
	targetw[tot]=w;
}
bool vis1[600005],vis2[600005],vis3[600005];
void dfs1(int x){
	vis1[x]=1;
	for(int i=0;i<v[x].size();i++){
		int y=v[x][i];
		if(vis1[y]) continue;
		dfs1(y);
	}
}
void dfs2(int x){
	vis2[x]=1;
	for(int i=0;i<t[x].size();i++){
		int y=t[x][i];
		if(vis2[y]) continue;
		dfs2(y);
	}
}
int e[600005];
void dfs3(int x){
	vis3[x]=1;
	for(int i=head[x];i;i=nxt[i]){
		int y=targetx[i],w=targetw[i],z=(y<=n?y:y-n);
		if(!vis1[z] || !vis2[z]) continue;
		if(vis3[y]){
			ans=__gcd(ans,w+e[x]-e[y]);
		}else{
			e[y]=e[x]+w;
			dfs3(y);
		}
	}
}
signed main(){
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	cin>>n>>m;
	for(int i=1;i<=m;i++){
		cin>>x>>y;
		v[x].push_back(y);
		t[y].push_back(x);
		add(x+n,y,0);
		add(y,x+n,0);
	}
	for(int i=1;i<=n;i++){
		cin>>a[i];
		if(a[i]!=-1){
			add(i,i+n,a[i]);
		    add(i+n,i,-a[i]);
		}
	}
	add(1,n+n,0);
	dfs1(1);
	dfs2(n);
	for(int i=1;i<=n;i++){
		if(!vis1[i] || !vis2[i]) continue;
		if(!vis3[i]) dfs3(i);
		if(!vis3[i+n]) dfs3(i+n);
	}
	if(!ans) cout<<-1;
	else cout<<abs(ans);
	return 0;
}
posted @ 2025-03-27 21:14  _Kenma  阅读(15)  评论(0)    收藏  举报