• CF1515G Phoenix and Odometers 题解


    Codeforces
    Luogu

    Description.

    给定一张有向图,\(q\) 次询问,每次询问是否存在一个经过 \(v\) 的环,满足路径长 \(\equiv s\pmod t\)

    Solution.

    奶到 \(\gcd\) 了,可能再想一步就想通了,但是停下了,有点可惜。

    考虑一个环肯定存在于一个强连通分量里,而每个强连通分量都可以构造一个环经过所有点,所以每个强连通分量答案都一样。
    所以首先 tarjan 缩点,然后对每个强连通分量求答案。

    对于每个强连通分量,很显然能否就与它所有环 \(\gcd\) 的答案有关了,设这个东西是 \(w\)
    设路径长为 \(l\),那如果 \(l\bmod\gcd(s,w)\) 不为 \(0\),必然不行,否则根据裴蜀定理一定可行。
    然后我们只需要统计所有环的 \(\gcd\) 就行了。
    直接搞一个 \(\text{dfs}\) 序,然后对于每条非树边加入成环大小即可。
    证明略,感性理解一下发现是对的,证明详见洛谷题解区。

    Coding.

    点击查看不好看代码
    //是啊,你就是那只鬼了,所以被你碰到以后,就轮到我变成鬼了{{{
    #include<bits/stdc++.h>
    using namespace std;typedef long long ll;
    template<typename T>inline void read(T &x)
    {
        x=0;char c=getchar(),f=0;
        for(;c<48||c>57;c=getchar()) if(!(c^45)) f=1;
        for(;c>=48&&c<=57;c=getchar()) x=(x<<1)+(x<<3)+(c^48);
        f?x=-x:x;
    }
    template<typename T,typename...L>inline void read(T &x,L&...l) {read(x),read(l...);}/*}}}*/
    const int N=200005;struct edge{int to,w,nxt;}e[N];int n,m,q,et,head[N];
    inline void adde(int x,int y,int w) {e[++et]=(edge){y,w,head[x]},head[x]=et;}
    int dt,dfn[N],low[N],cl[N],st[N],tp,ct;ll ds[N],gd[N];char tv[N],vs[N];
    inline void tarjan(int x)
    {
    	dfn[x]=low[x]=++dt,st[++tp]=x,tv[x]=1;
    	for(int i=head[x];i;i=e[i].nxt)
    		if(!dfn[e[i].to]) tarjan(e[i].to),low[x]=min(low[x],low[e[i].to]);
    		else if(tv[e[i].to]) low[x]=min(low[x],dfn[e[i].to]);
    	if(low[x]==dfn[x]) {int y=++ct;do tv[y=st[tp--]]=0,cl[y]=ct;while(y^x);}
    }
    inline void dfs(int x,int col)
    {
    	vs[x]=1;for(int i=head[x];i;i=e[i].nxt) if(cl[e[i].to]==col)
    	{
    		if(!vs[e[i].to]) ds[e[i].to]=ds[x]+e[i].w,dfs(e[i].to,col);
    		else gd[col]=__gcd(gd[col],ds[x]+e[i].w-ds[e[i].to]);
    	}
    }
    int main()
    {
    	read(n,m);for(int i=1,x,y,w;i<=m;i++) read(x,y,w),adde(x,y,w);
    	for(int i=1;i<=n;i++) if(!dfn[i]) tarjan(i);
    	for(int i=1;i<=n;i++) if(!vs[i]) dfs(i,cl[i]);
    	//for(int i=1;i<=n;i++) printf("%d%c",cl[i],i==n?'\n':' ');
    	//for(int i=1;i<=ct;i++) printf("%lld%c",gd[i],i==ct?'\n':' ');
    	int Ca,v;read(Ca);for(ll s,t;Ca--;) read(v,s,t),puts(s%__gcd(t,gd[cl[v]])?"NO":"YES");
    	return 0;
    }
    
  • 相关阅读:
    python面向对象之类,对象
    面向对象简介
    序列化模块
    sys模块简单使用
    day26作业
    day22
    day21作业
    day21
    day20作业
    day20
  • 原文地址:https://www.cnblogs.com/pealfrog/p/15216584.html
Copyright © 2020-2023  润新知