首页 > 其他分享 >题解 P9981 [USACO23DEC] Minimum Longest Trip G

题解 P9981 [USACO23DEC] Minimum Longest Trip G

时间:2024-03-31 19:23:19浏览次数:26  
标签:fa USACO23DEC 题解 P9981 int MAXN long && include

【洛谷专栏】

题意

\(N\) 个点 \(M\) 条边的有向无环图,对于每一个点 \(i\) 你需要求出一条从 \(i\) 出发的最长路径且路径上边权组成的序列字典序最小。

求每一条路径的长度和边权和。

分析

最长的路径很好求,在 DAG 上拓扑排序后动态规划即可。(具体的实现可以参考 OI-Wiki

现在的问题就变成了怎么求字典序最小。

如果朴素的进行比较判断时间复杂度在最坏情况下是 \(O(N^2)\),难以通过此题,考虑优化。

一个序列比等长的另一个序列字典序更小,当且仅当在它们不同的第一个位置,前者比后者的元素更小。

说明序列的字典序只和其中一个数有关,于是需要一个更快的方法,来找到第一个不同的位置。

类似于字符串哈希的方法,可以预处理前缀哈希使得单次查询一个子串的复杂度变成 \(O(1)\)。但是因为没有记录一条链上的所有节点所以不便于二分,考虑换成倍增。

然后是类似于最近公共祖先的倍增写法,不断的向上跳找到第一个标签值不同的位置,然后比较即可。

时间复杂度 \(O(M \log N)\),可以通过此题。

代码

//the code is from chenjh
#include<cstdio>
#include<queue>
#include<utility>
#include<vector>
#define MAXN 200002
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int,int> PII;
const unsigned int p=131;//自然溢出哈希底数。
int n,m,in[MAXN];
int tp[MAXN],c=0;
vector<PII> G[MAXN];
int f[MAXN];//最长链的长度。
LL s[MAXN];//标签和。
int fa[MAXN][19];//链上节点倍增。
ULL pn[MAXN<<2],hs[MAXN][19];//倍增哈希。
int main(){
	pn[0]=1;
	for(int i=1,mi=MAXN<<2;i<mi;i++) pn[i]=pn[i-1]*p;//预处理哈希底数的幂次。
	scanf("%d%d",&n,&m);
	for(int i=0,u,v,w;i<m;i++)
		scanf("%d%d%d",&u,&v,&w),
		G[u].emplace_back(v,w),++in[v];
	queue<int> Q;
	for(int i=1;i<=n;i++)if(!in[i]) Q.push(i);
	for(int u;!Q.empty();){//对图进行拓扑排序。
		u=Q.front(),Q.pop();
		tp[++c]=u;
		for(const auto&[v,w]:G[u])if(!--in[v]) Q.push(v);
	}
	for(int i=n,u;i>0;--i){//根据拓扑序倒推。
		u=tp[i];
		for(const auto&[v,w]:G[u])
			if(f[u]<f[v]+1||(f[u]==f[v]+1&&(ULL)w<*hs[u]))//存在更长的路径或长度相同但当前标签比答案更小就直接更新答案。
				f[u]=f[v]+1,s[u]=s[v]+w,*fa[u]=v,*hs[u]=w;
			else if(f[u]==f[v]+1&&(ULL)w==*hs[u]){//长度相同且第一位也相同,才有必要进行进一步的判断。
				int x=*fa[u],y=v;
				for(int k=18;k>=0;--k)if(fa[x][k] && fa[y][k] && hs[x][k]==hs[y][k])
					x=fa[x][k],y=fa[y][k];//向上跳找到第一个不同的点。
				if(x&&y&&*hs[y]<*hs[x])
					f[u]=f[v]+1,s[u]=s[v]+w,*fa[u]=v,*hs[u]=w;//不同的位置更小,更新答案。
			}
		for(int k=1;k<19;k++)
			fa[u][k]=fa[fa[u][k-1]][k-1],
			hs[u][k]=hs[fa[u][k-1]][k-1]*pn[1<<(k-1)]+hs[u][k-1];//倍增处理祖先和祖先的哈希。
	}
	for(int i=1;i<=n;i++) printf("%d %lld\n",f[i],s[i]);
	return 0;
}

标签:fa,USACO23DEC,题解,P9981,int,MAXN,long,&&,include
From: https://www.cnblogs.com/Chen-Jinhui/p/18107123

相关文章

  • Minlexes题解
    \(\texttt{ProblemLink}\)简要题意在一个字符串\(s\)中,对于每个后缀,任意删掉一些相邻的相同的字符,使得字符串字典序最小。注意:删掉之后拼起来再出现的相邻相同字符不能够删除。思路倍增好题。发现存在局部最优解(最优子结构),并且可以转移到其它结点,可以考虑使用dp。那就......
  • Tomcat启动失败,窗口一闪而过问题解决
    在启动Tomcat时窗口一闪而过,解决方法:在Tomcat安装目录\bin下启动cmd,或在C盘启动后跳转到Tomcat安装目录\bin,输入startup.bat(一定要先做这步,确保具体问题,再根据具体问题百度,不然又是配置JRE,又是配置Tomcat环境变量,最后做了无用功),如果显示如下:先确保java环境变量没问题,我的java......
  • 题解:AT_arc175_b [ARC175B] Parenthesis Arrangemen
    前言警示后人:字符串最大长度为\(65535\),会\(RE\)!!!\(10^7\)会爆栈!!!题意给出一个括号序列\(s\),有两种操作方式,交换两个字符需要花费\(A\),直接修改一个字符需要花费\(B\),求使这个序列合法需要的最小花费。分析我们可以先将\(s\)中能匹配的括号序列消除掉(即括号匹配......
  • [蓝桥杯] 管道 java题解
    importjava.util.*;/***管道*其实这道题核心根本不用管管道左边的如何,我们可以把左边当成注水口*/publicclassMain{staticintn;staticint[][]pipes;//阀门安排的地方staticintlen;//管道长度publicstaticvoidmain(String[]a......
  • AtCoder Beginner Contest 347 A-F 题解
    A-DivisibleQuesiton给你正整数\(N\)和\(K\),以及长度为\(N\)的序列\(A\)。提取\(A\)中所有是\(K\)倍数的元素,除以\(K\),并打印商。Solution判断\(A_i\%K\)的值是否为\(0\),如果非\(0\)则表示可以整除Code#include<bits/stdc++.h>usingnamespacest......
  • CCF-CSP真题《202309-3 梯度求解》题解
    题目string转longlong忘记处理负数卡了半天,服了#include<iostream>#include<cstdio>#include<cstring>#include<sstream>typedeflonglongll;usingnamespacestd;intn,m,temp;lla[302];stringf,x,b;llmod=1e9+7;structnode{ stringcon; n......
  • 矩阵匹配【华为OD机试JAVA&Python&C++&JS题解】
    一.题目-矩阵匹配从一个NM(N<=M)的矩阵中选出N个数,任意两个数字不能在同一行或同一列,求选出来的N个数中第K大的数字的最小值是多少。输入描述:输入矩阵要求:1<=K<=N<=M<=150输入格式:NMKNM矩阵输出描述:N*M的矩阵中可以选出M!/N!种组合数组,每个组合数组中第K大的数中的......
  • 文本统计分析【华为OD机试JAVA&Python&C++&JS题解】
    一.题目-文本统计分析有一个文件,包含以一定规则写作的文本,请统计文件中包含的文本数量规则如下文本以";“分隔,最后一条可以没有”;",但空文本不能算语句,比如"COMMANDA;;"只能算一条语句.注意,无字符/空白字符/制表符都算作"空"文本文本可以跨行,比如下面,......
  • [ABC347C] Ideal Holidays题解
    [ABC347C]IdealHolidays题解原题传送门原题传送门(洛谷)​ 题意翻译:​ 在\(AtCoder\)王国中,一个周有\(A+B\)天。其中在一周中,\([1,A]\)天是假日,\([A+1,B]\)天是工作日。​ 高桥有\(N\)个计划,第\(i\)个计划安排在\(i\)天后。他不知道今天是周几,但他想知道是否......
  • AT_abc347_d 的题解
    (一)数学题。根据\(C\)的值,可以得出\(x\)和\(y\)有\(s1+s\)个相同的数位和\(s2\)个不同的数位。\(s1\)是\(C\)的二进制中\(0\)的数量,\(s2\)是\(C\)的二进制中\(1\)的数量。\(x\)和\(y\)可以通过在开头放\(s\)个\(1\)的方式既不改变异或大小,又能凑到......