题意

给定一个 \(n\) 点 \(m\) 边的边权非负的有向图,边有字符,求以每个点为开头的最长路字典序最小的路径 \(hash\) 值。

\(n,m\leq 10^6\)

分析

  • 首先建反图拓扑排序后入度不为0的点的答案为 \(inf\) 。

  • 在 \(dep\) 相同时,怎么比较两种转移的优劣?注意到建完反图之后可以通过判定两个转移第一个字典序不同的位置的大小,可以倍增\(+hash\) 实现。

  • 总时间复杂度为 \(O(20*(n+m))\)。

代码

#include<bits/stdc++.h>
using namespace std;
#define go(u) for(int i=head[u],v=e[i].to;i;i=e[i].last,v=e[i].to)
#define rep(i,a,b) for(int i=a;i<=b;++i)
#define pb push_back
typedef long long LL;
inline int gi(){
int x=0,f=1;char ch=getchar();
while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
while(isdigit(ch)){x=(x<<3)+(x<<1)+ch-48;ch=getchar();}
return x*f;
}
template<typename T>inline bool Max(T &a,T b){return a<b?a=b,1:0;}
template<typename T>inline bool Min(T &a,T b){return b<a?a=b,1:0;}
const int N=1e6 + 7,mod=998244353;
int n,m,edc,hd=1,tl;
int head[N],ind[N],q[N],dep[N],to[N][21];
LL h[N][21],bin[N];
struct edge{
int last,to,c;
edge(){}edge(int last,int to,int c):last(last),to(to),c(c){}
}e[N*2];
void Add(int a,int b,int c){
e[++edc]=edge(head[a],b,c),head[a]=edc;++ind[b];
}
bool better(int x,int y){
for(int i=20;~i;--i)
if(h[x][i]==h[y][i]) x=to[x][i],y=to[y][i];
return h[x][0]<h[y][0];
}
void topo(){
rep(i,1,n) if(!ind[i]) q[++tl]=i,dep[i]=1;
for(;hd<=tl;++hd){
int u=q[hd];
rep(i,1,20){
to[u][i]=to[to[u][i-1]][i-1];
h[u][i]=(h[u][i-1]+h[to[u][i-1]][i-1]*bin[1<<i-1])%mod;
}
go(u){
if(dep[u]+1>dep[v]) dep[v]=dep[u]+1,to[v][0]=u,h[v][0]=e[i].c;
else if(dep[u]+1==dep[v]){
if(!to[v][0]||e[i].c<h[v][0]||(e[i].c==h[v][0]&&better(u,to[v][0])))
to[v][0]=u,h[v][0]=e[i].c;
}
if(--ind[v]==0) q[++tl]=v;
}
}
rep(i,1,n)
if(ind[i]) puts("Infinity");
else printf("%lld\n",29*h[i][20]%mod);
}
int main(){
n=gi(),m=gi();
for(int i=1,a,b,c;i<=m;++i){
a=gi(),b=gi(),c=gi();
Add(b,a,c);
}
bin[0]=1;
rep(i,1,N-1) bin[i]=1ll*bin[i-1]*29%mod;
topo();
return 0;
}

还有一种做法,将所有同层的点根据字典序优劣排序后转移到下一层,可以归纳证明。

#include<bits/stdc++.h>
using namespace std;
#define go(u) for(int i=head[u],v=e[i].to;i;i=e[i].last,v=e[i].to)
#define rep(i,a,b) for(int i=a;i<=b;++i)
#define pb push_back
typedef long long LL;
inline int gi(){
int x=0,f=1;char ch=getchar();
while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
while(isdigit(ch)){x=(x<<3)+(x<<1)+ch-48;ch=getchar();}
return x*f;
}
template<typename T>inline bool Max(T &a,T b){return a<b?a=b,1:0;}
template<typename T>inline bool Min(T &a,T b){return b<a?a=b,1:0;}
const int N=1e6 + 7,mod=998244353,inf=0x3f3f3f3f;
typedef pair<int,int> pii;pii f[N];
#define mp make_pair
int n,m,edc,hd=1,tl;
int head[N],ind[N],q[N],dep[N],rk[N],h[N];
struct edge{
int last,to,c;
edge(){}edge(int last,int to,int c):last(last),to(to),c(c){}
}e[N*2];
void Add(int a,int b,int c){
e[++edc]=edge(head[a],b,c),head[a]=edc;++ind[b];
}
vector<int>G[N];
bool cmp(int a,int b){
return f[a]<f[b];
}
void topo(){
rep(i,1,n) if(!ind[i]) q[++tl]=i,dep[i]=1,f[i]=mp(0,0);
else f[i]=mp(inf,inf);
for(;hd<=tl;++hd){
int u=q[hd];
G[dep[u]].pb(u);
go(u){
Max(dep[v],dep[u]+1);
if(--ind[v]==0) q[++tl]=v;
}
}
rep(j,1,n){
for(auto u:G[j])
go(u)if(dep[u]+1==dep[v]){
if(mp(e[i].c,rk[u])<f[v]){
f[v]=mp(e[i].c,rk[u]);
h[v]=(1ll*h[u]*29+e[i].c)%mod;
}
}
sort(G[j+1].begin(),G[j+1].end(),cmp);
rep(i,0,(int)G[j+1].size()-1) rk[G[j+1][i]]=i;
}
rep(i,1,n)
if(ind[i]) puts("Infinity");
else printf("%lld\n",1ll*29*h[i]%mod);
}
int main(){
n=gi(),m=gi();
for(int i=1,a,b,c;i<=m;++i){
a=gi(),b=gi(),c=gi();
Add(b,a,c);
}
topo();
return 0;
}

牛客网NOIP赛前集训营-提高组(第六场)-A-最长路[拓扑排序+hash+倍增]的更多相关文章

  1. 牛客网NOIP赛前集训营-普及组(第二场)和 牛客网NOIP赛前集训营-提高组(第二场)解题报告

    目录 牛客网NOIP赛前集训营-普及组(第二场) A 你好诶加币 B 最后一次 C 选择颜色 D 合法括号序列 牛客网NOIP赛前集训营-提高组(第二场) A 方差 B 分糖果 C 集合划分 牛客网N ...

  2. 牛客网NOIP赛前集训营-提高组(第二场)A 方差

    链接:https://www.nowcoder.com/acm/contest/173/A来源:牛客网 题目描述 一个长度为 m 的序列 b[1...m] ,我们定义它的方差为 ,其中  表示序列的平 ...

  3. [牛客网NOIP赛前集训营-提高组(第一场)]C.保护

    链接:https://www.nowcoder.com/acm/contest/172/C来源:牛客网 题目描述 C国有n个城市,城市间通过一个树形结构形成一个连通图.城市编号为1到n,其中1号城市为 ...

  4. 牛客网NOIP赛前集训营-提高组(第一场)

    牛客的这场比赛感觉真心不错!! 打得还是很过瘾的.水平也比较适合. T1:中位数: 题目描述 小N得到了一个非常神奇的序列A.这个序列长度为N,下标从1开始.A的一个子区间对应一个序列,可以由数对[l ...

  5. 比赛总结——牛客网 NOIP赛前集训营提高组模拟第一场

    第一场打的很惨淡啊 t1二分+前缀最小值没想出来,20分的暴力也挂了,只有10分 t2数位dp,调了半天,结果因为忘了判0的特殊情况WA了一个点,亏死 t3emmmm.. 不会 imone说是DSU ...

  6. 牛客网NOIP赛前集训营-提高组(第一场)B 数数字

    数数字 思路: 数位dp 代码: #pragma GCC optimize(2) #pragma GCC optimize(3) #pragma GCC optimize(4) #include< ...

  7. 牛客网NOIP赛前集训营-提高组(第一场)A 中位数

    中位数 思路: 二分答案 代码: #pragma GCC optimize(2) #pragma GCC optimize(3) #pragma GCC optimize(4) #include< ...

  8. 牛客网NOIP赛前集训营 提高组 第5场 T2 旅游

    [题解] 我们可以发现不在最小生成树上的边一定不能多次经过,因为一条不在最小生成树上的边(u,v)的边权比最小生成树上(u,v)之间的路径更长,选择不在最小生成树上的边一定不划算. 我们还需要确定最小 ...

  9. 牛客网NOIP赛前集训营-提高组(第四场)游记

    牛客网NOIP赛前集训营-提高组(第四场)游记 动态点分治 题目大意: \(T(t\le10000)\)组询问,求\([l,r]\)中\(k(l,r,k<2^{63})\)的非负整数次幂的数的个 ...

  10. 牛客网NOIP赛前集训营-提高组(第四场)B区间

    牛客网NOIP赛前集训营-提高组(第四场)B区间 题目描述 给出一个序列$ a_1  \dots   a_n$. 定义一个区间 \([l,r]\) 是好的,当且仅当这个区间中存在一个 \(i\),使得 ...

随机推荐

  1. 使用CAReplicatorLayer [1]

    使用CAReplicatorLayer [1] 说明 https://developer.apple.com/library/ios/documentation/GraphicsImaging/Ref ...

  2. 一、JDBC的概述 二、通过JDBC实现对数据的CRUD操作 三、封装JDBC访问数据的工具类 四、通过JDBC实现登陆和注册 五、防止SQL注入

    一.JDBC的概述###<1>概念 JDBC:java database connection ,java数据库连接技术 是java内部提供的一套操作数据库的接口(面向接口编程),实现对数 ...

  3. 一、MySQL中的索引 二、MySQL中的函数 三、MySQL数据库的备份和恢复 四、数据库设计和优化(重点)

    一.MySQL中的索引###<1>索引的概念 索引就是一种数据结构(高效获取数据),在mysql中以文件的方式存在.存储建立了索引列的地址或者指向. 文件 :(以某种数据 结构存放) 存放 ...

  4. Avito Code Challenge 2018

    第一次打CF,很菜,A了三道水题,第四题好像是是数位DP,直接放弃了.rateing从初始的1500变成了1499,还是绿名,这就很尴尬.之后觉得后面的题目也没有想象的那么难(看通过人数)过两天吧剩下 ...

  5. 在centos上安装smplayer播放器

    Smplayer是一个非常好用的媒体播放器.可以支持大部分的视频和音频文件.它支持音频轨道切换.允许调节亮度.对比度.色调.饱和度.伽玛值,按照倍速.4倍速等多种速度回放.还可以进行音频和字幕延迟调整 ...

  6. Linux - 常用归档、压缩命令

    1. ncompress compress命令是一个相当古老的 unix 档案压缩指令,压缩后的文件会加上一个 .Z 的后缀名,默认不会保留源文件.compress只能对文件进行压缩,若要压缩目录,先 ...

  7. macaca常见错误排查

    1.Error: cannot resolve path (or pattern) 'macaca-test' 这是因为执行run命令的时候未进入用例目录 C:\Users\Tony\node_mod ...

  8. bn两个参数的计算以及layer norm、instance norm、group norm

    bn一般就在conv之后并且后面再接relu 1.如果输入feature map channel是6,bn的gamma beta个数是多少个? 6个. 2.bn的缺点: BN会受到batchsize大 ...

  9. Python的编码注释【转】

    格式有多种,但必须有coding:[编码]或者coding=[编码],如: # -*- coding:utf-8 -*- #  coding:utf-8 # coding=utf-8 转自:https ...

  10. JavaScript小例子

    1. alert.html <html> <head> <title></title> <script type="text/javas ...