ARC144E 题解
DaiRuiChen007 · · 题解
Problem Link
题目大意
给定
n 个点m 条边的 DAG,点有点权,有一些点权不确定,找到一种方式最大化所有1\to n 路径点权和的\gcd 。数据范围:
n\le 3\times 10^5 。
思路分析
先删除所有不在
设答案为
把图看成无向图,只要处理所有环的
用可持久化并查集维护
时间复杂度
代码呈现
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int MAXN=3e5+5;
ll gcd(ll a,ll b) { return b?gcd(b,a%b):a; }
bool vs[MAXN],vt[MAXN];
vector <int> G[MAXN];
int n,m,fa[MAXN<<1];
ll a[MAXN],d[MAXN<<1],ans=0;
void dfs(int u) {
vs[u]=true;
if(u==n) vt[u]=true;
for(int v:G[u]) {
if(!vs[v]) dfs(v);
vt[u]|=vt[v];
}
}
int find(int x) {
if(x==fa[x]) return x;
int c=find(fa[x]);
d[x]+=d[fa[x]],fa[x]=c;
return c;
}
signed main() {
scanf("%d%d",&n,&m);
for(int i=1;i<=2*n;++i) fa[i]=i;
for(int i=1,u,v;i<=m;++i) {
scanf("%d%d",&u,&v);
G[u].push_back(v);
}
dfs(1);
if(!vt[1]) return puts("-1"),0;
for(int i=1;i<=n;++i) if(vt[i]) for(int j:G[i]) if(vt[j]) {
fa[find(i+n)]=find(j);
}
for(int i=1;i<=n;++i) {
scanf("%lld",&a[i]);
if(vt[i]&&~a[i]) {
if(find(i)!=find(i+n)) {
int x=find(i);
d[x]=a[i]-d[i],fa[x]=i+n;
} else {
ans=gcd(ans,abs(d[i+n]+a[i]-d[i]));
}
}
}
if(find(1)==2*n) ans=gcd(ans,d[1]);
printf("%lld\n",ans?ans:-1ll);
return 0;
}