CF1207F Koala and Notebook(BFS)

你可能会好奇为什么只有一个 BFS 的标签,却还能够排到 F 的位置。

因为它实在是太 简 单 了


首先,比较两个数,可以先比较两个数的长度,然后比较两个数看成数字串后的字典序。

不妨先把每条边拆成更多条边(中间加虚点),比如 233 拆成一条三条边的链,权分别是 2,3,3。

对于长度,根据 BFS 的性质,肯定是长度短的先访问。所以接下来只用稍微注意一下字典序。

其实也很简单:对每个出点,按照边权从小到大排序。可以证明访问到的点的答案(没取模)是单调不降的。

有个小细节:对于一些答案相同的点在队列里面,可能有一个更优的转移是从后面的点转移得到的。然而对于大多数代码(也可能只是我的)是只会访问一次(就像普通 BFS 一样),就把前面不够优的转移选了。

那么可以把答案相同的点一起处理,然后先枚举所有 0 边,再枚举所有 1 边……。

如何判断两个点答案相同?直接比复杂度就挂了,答案是取模过的看起来也一副不能比的样子。

然而……我不会了,所以我直接比了,然后就过了?

求证明/hack……

#include<bits/stdc++.h>
using namespace std;
typedef pair<int,int> PII;
const int maxn=1337337,mod=1000000007;
#define lson o<<1,l,mid
#define rson o<<1|1,mid+1,r
#define FOR(i,a,b) for(int i=(a);i<=(b);i++)
#define ROF(i,a,b) for(int i=(a);i>=(b);i--)
#define MEM(x,v) memset(x,v,sizeof(x))
inline int read(){
    int x=0,f=0;char ch=getchar();
    while(ch<'0' || ch>'9') f|=ch=='-',ch=getchar();
    while(ch>='0' && ch<='9') x=x*10+ch-'0',ch=getchar();
    return f?-x:x;
}
int n,m,cnt,h,r,q[maxn],ans[maxn];
vector<int> e[maxn][10];
bool vis[maxn],ch[maxn];
int main(){
    cnt=n=read();m=read();
    FOR(i,1,m){
        int u=read(),v=read();
        int tmp=i,pre=v;
        while(tmp>9){
            e[++cnt][tmp%10].push_back(pre);
            tmp/=10;pre=cnt;
        }
        e[u][tmp].push_back(pre);
        tmp=i;pre=u;
        while(tmp>9){
            e[++cnt][tmp%10].push_back(pre);
            tmp/=10;pre=cnt;
        }
        e[v][tmp].push_back(pre);
    }
    q[h=r=1]=1;
    vis[1]=true;
    ans[1]=0;
    while(h<=r){
        int L=h,R=0;
        FOR(i,h+1,r) if(ch[q[i]]){R=i-1;break;}
        if(!R) R=r;
        FOR(j,0,9) FOR(i,L,R){
            int u=q[i];
            FOR(k,0,(int)e[u][j].size()-1){
                int v=e[u][j][k];
                if(vis[v]) continue;
                vis[v]=true;
                ans[v]=(10ll*ans[u]+j)%mod;
                if(ans[q[r]]!=ans[v]) ch[v]=true;
                q[++r]=v;
            }
        }
        h=R+1;
    }
    FOR(i,2,n) printf("%d\n",ans[i]);
}

转载于:https://www.cnblogs.com/1000Suns/p/11559108.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值