显然这条路径只能在$v_{i}$所在的强连通分量内部,不妨仅考虑这个强连通分量
对这个强连通分量dfs,得到一棵外向树(不妨以1为根)
考虑一条边$(u,v,l)$,由于强连通,总存在一条从$v$到$u$的路径,经过这条路径$t_{i}$次,再经过$u$到$v$这条边$t_{i}-1$次,即从$v$到达了$u$,且总边权$equiv -l(mod t_{i})$
由此,不妨将$(v,u,-l)$也作为一条边加入图中,显然不影响(以下称这条边为$(u,v,l)$的反向边)
此时,令$dep_{x}$为1通过树边走到$x$的权值和,那么从$x$到$y$通过树边及其反向边的最短路,权值和即
$$
(dep_{lca(x,y)}-dep_{x})+(dep_{y}-dep_{lca(x,y)})=dep_{y}-dep_{x}
$$
显然若没有非树边,从$x$到$y$的任意一条路径(之前仅考虑最短路)权值和都为$dep_{y}-dep_{x}$(显然每一条边都是最短路,前后项相消即可)
考虑非树边$(u,v,l)$,若从$x$到$y$的路径每经过一次$(u,v,l)$,实际上即让边权和加$l-(dep_{v}-dep_{u})$,最后统计所有非树边的贡献和即为总边权和
另一方面,我们显然可以经过每一条非树边任意次
由此,对每一条非树边$(u,v,l)$求出$l-(dep_{v}-dep_{u})$,假设依次为$a_{1},a_{2},...,a_{s}$,问题即判定是否存在一组解$x_{i}in N$,使得$sum_{j=1}^{s}x_{j}a_{j}equiv -s_{i}(mod t_{i})$
根据数论知识,这显然等价于$gcd(gcd_{i=1}^{s}a_{i},t_{i})mid s_{i}$,判定即可
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define N 200005 4 #define ll long long 5 struct Edge{ 6 int nex,to,len; 7 }edge[N<<1]; 8 int E,n,m,q,x,y,z,scc,head[N],head_rev[N],dfn[N],vis[N],bl[N]; 9 ll dep[N],ans[N]; 10 ll gcd(ll x,ll y){ 11 if (!y)return x; 12 return gcd(y,x%y); 13 } 14 void add(int x,int y,int z){ 15 edge[E].nex=head[x]; 16 edge[E].to=y; 17 edge[E].len=z; 18 head[x]=E++; 19 } 20 void add_rev(int x,int y,int z){ 21 edge[E].nex=head_rev[x]; 22 edge[E].to=y; 23 edge[E].len=z; 24 head_rev[x]=E++; 25 } 26 void dfs1(int k){ 27 if (vis[k])return; 28 vis[k]=1; 29 for(int i=head[k];i!=-1;i=edge[i].nex)dfs1(edge[i].to); 30 dfn[++dfn[0]]=k; 31 } 32 void dfs2(int k,ll s){ 33 if (bl[k])return; 34 bl[k]=scc; 35 dep[k]=s; 36 for(int i=head_rev[k];i!=-1;i=edge[i].nex)dfs2(edge[i].to,s+edge[i].len); 37 } 38 int main(){ 39 scanf("%d%d",&n,&m); 40 memset(head,-1,sizeof(head)); 41 memset(head_rev,-1,sizeof(head_rev)); 42 for(int i=1;i<=m;i++){ 43 scanf("%d%d%d",&x,&y,&z); 44 add(x,y,z); 45 add_rev(y,x,z); 46 } 47 for(int i=1;i<=n;i++) 48 if (!vis[i])dfs1(i); 49 for(int i=n;i;i--) 50 if (!bl[dfn[i]]){ 51 scc++; 52 dfs2(dfn[i],0); 53 } 54 for(int x=1;x<=n;x++) 55 for(int j=head[x];j!=-1;j=edge[j].nex){ 56 y=edge[j].to,z=edge[j].len; 57 if (bl[x]==bl[y])ans[bl[x]]=gcd(ans[bl[x]],z-(dep[x]-dep[y])); 58 } 59 scanf("%d",&q); 60 for(int i=1;i<=q;i++){ 61 scanf("%d%d%d",&x,&y,&z); 62 if (y%gcd(ans[bl[x]],z)==0)printf("YES "); 63 else printf("NO "); 64 } 65 }