[cf1515G]Phoenix and Odometers
显然这条路径只能在vi所在的强连通分量内部,不妨仅考虑这个强连通分量
对这个强连通分量dfs,得到一棵外向树(不妨以1为根)
考虑一条边(u,v,l),由于强连通,总存在一条从v到u的路径,经过这条路径ti次,再经过u到v这条边ti−1次,即从v到达了u,且总边权≡−l(mod ti)
由此,不妨将(v,u,−l)也作为一条边加入图中,显然不影响(以下称这条边为(u,v,l)的反向边)
此时,令depx为1通过树边走到x的权值和,那么从x到y通过树边及其反向边的最短路,权值和即
(deplca(x,y)−depx)+(depy−deplca(x,y))=depy−depx
显然若没有非树边,从x到y的任意一条路径(之前仅考虑最短路)权值和都为depy−depx(显然每一条边都是最短路,前后项相消即可)
考虑非树边(u,v,l),若从x到y的路径每经过一次(u,v,l),实际上即让边权和加l−(depv−depu),最后统计所有非树边的贡献和即为总边权和
另一方面,我们显然可以经过每一条非树边任意次
由此,对每一条非树边(u,v,l)求出l−(depv−depu),假设依次为a1,a2,...,as,问题即判定是否存在一组解xi∈N,使得∑sj=1xjaj≡−si(mod ti)
根据数论知识,这显然等价于gcd,判定即可
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\n"); 63 else printf("NO\n"); 64 } 65 }
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步