牛客网NOIP赛前集训营-提高组(第六场)A-最长路
题目描述
有一张 n 个点 m 条边的有向图,每条边上都带有一个字符,字符用一个数字表示。
求以每个点为起点的最长路,输出走过的边的字符构成的字符串的字典序最小的方案。
为了方便,你需要这样输出方案:
如果最长路无限长,则输出Infinity
否则假设方案走过的边的字符依次为 w1,w2,..wk ,输出
输入描述:
第一行两个整数 n,m ,表示有向图的结点个数和边数。
接下来 m 行,每行三个整数 x,y,w ,表示有一条从 x 连向 y 的边,上面有字符 w 。
输出描述:
对于每个询问,输出一行,表示答案。
示例1
输入
5 6
1 2 0
2 1 0
3 4 2
4 5 3
4 5 1
3 5 1
输出
Infinity
Infinity
899
29
0
说明
以第 1 个点和第 2 个点为起点的最长路都是无限长,输出Infinity;
以第 3 个点为起点的最长路为 2 条边,有两种方案,走过的边的字符构成的字符串分别为
{2,3} 和 { 2,1} ,其中 { 2,1} 的字典序更小,所以输出 。
以第 4 个点为起点的最长路为 1 条边,有两种方案,走过的边的字符构成的字符串分别为
{3} 和 { 1} ,其中 { 1} 的字典序更小,所以输出 。
以第 5 个点为起点的最长路为 0 条边,注意此时应输出 0 。
备注:
全部的输入数据满足:
- \(1 ≤ n ≤ 1000000\)
- \(1 ≤ m ≤ 1000000\)
- \(0 ≤ \text{字符} ≤ 10^9\)
各个测试点的性质如下:(若为空,则表示没有特殊性质)
Solution
显然如果一个能连到一个环那就是Infinity 。
那么去掉这些点以后就是个DAG,显然跑DP。其中前80分都可以直接暴力DP得来。
唯一的问题是如何快速判断两个决策的优劣。
如果是两个给你的字符串保证一样长,让你比较字典序,可以最多做\(O(n)\)的预处理,要求比较在\(O(\log n)\)做完。那么显然做一个哈希,然后二分它们开始不一样的位置或者倍增找。找到以后比较下一位。
那么在这个题里面,显然不能二分,因为没有明显的序列。那么考虑倍增,每个点维护其最优决策里\(s[i][j]\)表示\(i\)这个点往后\(2^j\)位的点。哈希值也很好维护的,所以就做完了。
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<vector>
using namespace std;
#define lowbit(x) ((x)&(-(x)))
#define REP(i,a,n) for(register int i=(a);i<=(n);++i)
#define PER(i,a,n) for(register int i=(a);i>=(n);--i)
#define FEC(i,x) for(register int i=head[x];i;i=g[i].ne)
template<typename A>inline void read(A&a){a=0;char c=0;int f=1;while(c<'0'||c>'9')(c=getchar())=='-'?f=-1:0;while(c>='0'&&c<='9')a=(a<<3)+(a<<1)+c-'0',c=getchar();f==-1?a=-a:0;}
char buf[30];template<typename A>inline void write(A a){if(a<0)putchar('-'),a=-a;int top=0;if(!a)buf[top=1]='0';while(a)buf[++top]=a%10+'0',a/=10;while(top)putchar(buf[top--]);}
typedef long long ll;typedef unsigned long long ull;
template<typename A,typename B>inline bool SMAX(A&x,const B&y){return y>x?x=y,1:0;}
template<typename A,typename B>inline bool SMIN(A&x,const B&y){return y<x?x=y,1:0;}
const int N=1000000+7,MOD=998244353,base=3007,LOG=21;
int n,m,x,y,z;
struct Edge{int to,ne,w;}g[N];int head[N],tot;
inline void Addedge(int x,int y,int z){g[++tot].to=y;g[tot].w=z;g[tot].ne=head[x];head[x]=tot;}
int vis[N],hkk[N];int s[N][LOG];ull bin[N];
struct Node{
int c,hash;ull h2;
inline bool Check(){return ~c;}
}dp[N];
inline bool cmp(int a,int b){
for(register int i=LOG-1;i>=0;--i)
if(s[a][i]&&s[b][i]&&dp[a].h2-dp[s[a][i]].h2*bin[1<<i]==dp[b].h2-dp[s[b][i]].h2*bin[1<<i])a=s[a][i],b=s[b][i];
return dp[a].h2-dp[s[a][0]].h2*base<dp[b].h2-dp[s[b][0]].h2*base;
}
inline Node DFS(int x){
if(hkk[x])return Node{-1,0,0};if(vis[x])return dp[x];
Node &ans=dp[x]={0,0,0};vis[x]=hkk[x]=1;int pre=-1,ch=1e9;
for(register int i=head[x];i;i=g[i].ne){
int y=g[i].to;Node &f=dp[0]=DFS(y);
if(!f.Check())return ans={-1,0,0};
else f.c++,f.hash=((ll)f.hash*29%MOD+(ll)g[i].w*29%MOD)%MOD,!~pre||f.c>ans.c||(f.c==ans.c&&(g[i].w<ch||(g[i].w==ch&&cmp(y,pre))))?ans=f,pre=g[i].to,ch=g[i].w:0;
}hkk[x]=0;
ans.h2=ans.h2*base+ch;s[x][0]=pre;if(~pre)for(register int i=1;i<LOG;++i)s[x][i]=s[s[x][i-1]][i-1];
return ans;
}
inline void Work(){
bin[0]=1;for(register int i=1;i<=n;++i)bin[i]=bin[i-1]*base;
for(register int i=1;i<=n;++i){
DFS(i);
if(!dp[i].Check())puts("Infinity");
else write(dp[i].hash),putchar('\n');
}
}
int main(){
read(n),read(m);
for(register int i=1;i<=m;++i)read(x),read(y),read(z),Addedge(x,y,z);
Work();
}
牛客网NOIP赛前集训营-提高组(第六场)A-最长路的更多相关文章
- 牛客网NOIP赛前集训营-普及组(第二场)和 牛客网NOIP赛前集训营-提高组(第二场)解题报告
目录 牛客网NOIP赛前集训营-普及组(第二场) A 你好诶加币 B 最后一次 C 选择颜色 D 合法括号序列 牛客网NOIP赛前集训营-提高组(第二场) A 方差 B 分糖果 C 集合划分 牛客网N ...
- 牛客网NOIP赛前集训营-提高组(第二场)A 方差
链接:https://www.nowcoder.com/acm/contest/173/A来源:牛客网 题目描述 一个长度为 m 的序列 b[1...m] ,我们定义它的方差为 ,其中 表示序列的平 ...
- [牛客网NOIP赛前集训营-提高组(第一场)]C.保护
链接:https://www.nowcoder.com/acm/contest/172/C来源:牛客网 题目描述 C国有n个城市,城市间通过一个树形结构形成一个连通图.城市编号为1到n,其中1号城市为 ...
- 牛客网NOIP赛前集训营-提高组(第一场)
牛客的这场比赛感觉真心不错!! 打得还是很过瘾的.水平也比较适合. T1:中位数: 题目描述 小N得到了一个非常神奇的序列A.这个序列长度为N,下标从1开始.A的一个子区间对应一个序列,可以由数对[l ...
- 比赛总结——牛客网 NOIP赛前集训营提高组模拟第一场
第一场打的很惨淡啊 t1二分+前缀最小值没想出来,20分的暴力也挂了,只有10分 t2数位dp,调了半天,结果因为忘了判0的特殊情况WA了一个点,亏死 t3emmmm.. 不会 imone说是DSU ...
- 牛客网NOIP赛前集训营-提高组(第一场)B 数数字
数数字 思路: 数位dp 代码: #pragma GCC optimize(2) #pragma GCC optimize(3) #pragma GCC optimize(4) #include< ...
- 牛客网NOIP赛前集训营-提高组(第一场)A 中位数
中位数 思路: 二分答案 代码: #pragma GCC optimize(2) #pragma GCC optimize(3) #pragma GCC optimize(4) #include< ...
- 牛客网NOIP赛前集训营 提高组 第5场 T2 旅游
[题解] 我们可以发现不在最小生成树上的边一定不能多次经过,因为一条不在最小生成树上的边(u,v)的边权比最小生成树上(u,v)之间的路径更长,选择不在最小生成树上的边一定不划算. 我们还需要确定最小 ...
- 牛客网NOIP赛前集训营-提高组(第四场)游记
牛客网NOIP赛前集训营-提高组(第四场)游记 动态点分治 题目大意: \(T(t\le10000)\)组询问,求\([l,r]\)中\(k(l,r,k<2^{63})\)的非负整数次幂的数的个 ...
- 牛客网NOIP赛前集训营-提高组(第四场)B区间
牛客网NOIP赛前集训营-提高组(第四场)B区间 题目描述 给出一个序列$ a_1 \dots a_n$. 定义一个区间 \([l,r]\) 是好的,当且仅当这个区间中存在一个 \(i\),使得 ...
随机推荐
- 如何从word文档复制内容到富文本编辑器
在之前在工作中遇到在富文本编辑器中粘贴图片不能展示的问题,于是各种网上扒拉,终于找到解决方案,在这里感谢一下知乎中众大神以及TheViper. 通过知乎提供的思路找到粘贴的原理,通过TheViper找 ...
- Android解析编译之后的所有文件(so,dex,xml,arsc)格式
我们在之前一篇一篇介绍了如何解析Android中编译之后的所有文件格式,所有的工作都完成了,这里我们就来做个总结,我们为什么要做这些工作: 第一篇:解析so文件格式 点击进入 这里我们解析so文件,主 ...
- linux的shell脚本运行python程序
可以说和windows里的bat是一样的. python3 /opt/pyweibo/get_user_info.py 104501 104502 104503
- xpath进阶
目标: 抓取页面列表信息,并且获取第四个单元格得指定属性 代码: import requests from lxml import etree resp = requests.get('http:// ...
- C#如何获取系统downloads和documents路径
https://stackoverflow.com/questions/7672774/how-do-i-determine-the-windows-download-folder-path 如果你通 ...
- UNITY编辑器模式下static变量的坑
在unity中写编辑器扩展工具,如在编辑器中加个菜单,点击这个菜单项时执行打包功能. 类如下,其中的静态变量,如果每次进来不清空,则LIST会越来越大,打包函数执行完后系统不会帮我们清空 #if UN ...
- JS对象—字符串总结(创建、属性、方法)
1.创建字符串 1.1 new String(s) String和new一起使用,创建的是一个字符串对象,存放的是字符串s的表示. 1.2 String(s) ...
- Jmeter接口自动化培训
课程前提 速成班,讲的不会非常深,每个人基础不一样,但是实现接口自动化没有问题,因为jmeter更多的用来做性能测试.当然有兴趣我们也可以穿插一点 课程基本大纲 接口基础概念 部署本地测试环境(使用d ...
- jQuery基础--动画操作
三组基本动画 <!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset=" ...
- 《JAVA设计模式》之单例模式(Singleton)
在阎宏博士的<JAVA与模式>一书中开头是这样描述单例模式的: 作为对象的创建模式,单例模式确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例.这个类称为单例类. 单例模式的 ...