A题 生成树
对边排序,枚举最小边,然后不断加边,直到1,n在一个生成树中,用最大边更新答案
代码
B题 Dijkstra+构造
题意:给出一个大小为n的集合S,集合里有n个互不相同正整数.
有q个询问,每次询问是否能选择S中的一些数字 ( 同一个数字可以选择多次,也可以任何数字都不选),使它们相加的和为m.
本题思考的启发点是n和a1的数据比较小
对于S集合中的数,例如a1,考虑到如果x能够被表示出来,那么x+a1也一定能被表示出来。
故设d[r]为所有模a1余r的数中,能被表示出来的最小的数。
故可以表示出一个a1个节点a1*n条边的有向图。
d[0] = 0,丢入优先队列,然后对于q.top()的点连出的n条边进行松弛操作。
如果 d[u] + a[i] < d[(d[u] + a[i])] 则刷新并丢入队列。
跑出来的d[i],如果d[i] != INF则都是可以表示出来的。
对于每个询问判断 q >= d[q % a[1]]即可。
复杂度
na1loga1
代码
D题 拓扑排序
比较两个相邻字符串,对不同的字符建有向边,然后用拓扑排序,每次取出度数为0的字典序最小的小写字符去做,需要注意的是当两个字符串字符串前半部分相同,第二字符串比第一个短则不能构造出答案
代码
G题 Tarjan缩点+dfs
如果不逆行,那么答案就是1所在的强连通分量的点数
如果逆行了,那么逆行的边必然在缩点后的拓扑图上
假设逆行的边为u->v,那么该回路可分为1到v和u到1两部分
经过的最多点数即1到v与u到1路径上的最大点权和减去1的点权
(这里的点指的都是缩点后的点)
那么预处理拓扑图上1到每个点的最大点权和及每个点到1的最大点权和
枚举逆行的边即可得到答案。
刚开始dfs内部顺序写的有点问题,wa了半天
代码
H题 最小生成树
题意:
有一个长度为n的未知的01序列
询问区间l,r的异或和代价为C[l][r]
求通过询问得到该序列的最小代价
可以证明出询问集合构成的图有n条边且没有回路
建立n+1个虚拟点0到n,对于询问区间[l,r],在l-1与r之间连边,边权为C[l][r]
那么能得到该序列的极小询问集合会构成这n+1个点的一个生成树,代价为边权和
代码
I题 鼓轮模型+欧拉回路
参考here,可以百度鼓轮模型的构造方法
J题 差分约束
令sum[i]表示前i项的和(0<=i<=n,sum[0]=0)
那么题目的条件可转化为:
sum[i]-sum[i-p]>=s (p<=i<=n)
sum[i]-sum[i-q]<=t (q<=i<=n)
将第一个不等式取反,得到
sum[i-p]-sum[i]<=-s(p<=i<=n)
考虑最短路径的性质,令dis[i]表示从s到i的最短路,则对于图中存在的一条边(u,v),有
dis[v]<=dis[u]+w(u,v),即dis[v]-dis[u]<=w(u,v);
类比不等式,于是可建图,i向i-p引长度为-s的边,i-q向i引长度为t的边。
跑spfa,如果存在负环,则无解,
否则所得到的最短路的值就是sum[i]的一个解。