题解 [ARC144E] GCD of Path Weights
下文中设原图为
设答案非
考虑将
考虑先在
对于
对于剩下的点,我们考虑抓出
设
由于非树边一共只有
最后还有一个小问题:
综上,时间复杂度为
代码:
#include <stdio.h>
#include <stdlib.h>
typedef long long ll;
typedef struct {
int nxt;
int end;
ll dis;
} Edge;
int cnt1 = 0, cnt2 = 0, cnt3 = 0;
int head1[300007], head2[300007], head3[600007];
ll val[600007];
bool vis1[300007], vis2[300007], vis3[600007];
Edge edge1[300007], edge2[300007], edge3[1200007];
inline void add_edge1(int start, int end){
cnt1++;
edge1[cnt1].nxt = head1[start];
head1[start] = cnt1;
edge1[cnt1].end = end;
}
inline void add_edge2(int start, int end){
cnt2++;
edge2[cnt2].nxt = head2[start];
head2[start] = cnt2;
edge2[cnt2].end = end;
}
inline void add_edge3(int start, int end, ll dis){
cnt3++;
edge3[cnt3].nxt = head3[start];
head3[start] = cnt3;
edge3[cnt3].end = end;
edge3[cnt3].dis = dis;
}
void dfs1(int u){
vis1[u] = true;
for (int i = head1[u]; i != 0; i = edge1[i].nxt){
int x = edge1[i].end;
if (!vis1[x]) dfs1(x);
}
}
void dfs2(int u){
vis2[u] = true;
for (int i = head2[u]; i != 0; i = edge2[i].nxt){
int x = edge2[i].end;
if (!vis2[x]) dfs2(x);
}
}
ll gcd(ll a, ll b){
return b == 0 ? a : gcd(b, a % b);
}
ll dfs3(int u, int n){
ll ans = 0;
vis3[u] = true;
for (int i = head3[u]; i != 0; i = edge3[i].nxt){
int x = edge3[i].end, x_ = x <= n ? x : x - n;
if (vis1[x_] && vis2[x_]){
if (!vis3[x]){
val[x] = val[u] + edge3[i].dis;
ans = gcd(ans, dfs3(x, n));
} else {
ans = gcd(ans, llabs(val[x] - val[u] - edge3[i].dis));
}
}
}
return ans;
}
int main(){
int n, m;
ll ans = 0;
scanf("%d %d", &n, &m);
for (int i = 1; i <= m; i++){
int a, b, a_;
scanf("%d %d", &a, &b);
a_ = a + n;
add_edge1(a, b);
add_edge2(b, a);
add_edge3(a_, b, 0);
add_edge3(b, a_, 0);
}
for (int i = 1; i <= n; i++){
ll a;
scanf("%lld", &a);
if (a != -1){
int i_ = i + n;
add_edge3(i, i_, a);
add_edge3(i_, i, -a);
}
}
add_edge3(1, n * 2, 0);
dfs1(1);
dfs2(n);
for (int i = 1; i <= n; i++){
if (vis1[i] && vis2[i]){
int i_ = i + n;
if (!vis3[i]) ans = gcd(ans, dfs3(i, n));
if (!vis3[i_]) ans = gcd(ans, dfs3(i_, n));
}
}
if (ans == 0){
printf("-1");
} else {
printf("%lld", ans);
}
return 0;
}