代码
最小生成树
题目 | 题意 | 思路 | 代码 |
---|---|---|---|
买礼物 | 要买 B B B 样东西,这 B B B 样东西价格都是 A A A 元。如果你买了第 I I I 样东西,再买第 J J J 样,那么就可以只花 K I , J K_{I,J} KI,J 元, K I , J = K J , I K_{I,J}=K_{J,I} KI,J=KJ,I。最少要花多少钱。 1 ≤ B ≤ 500 , 0 ≤ A , K I , J ≤ 1000 1\le B\le500,0\le A,K_{I,J}\le1000 1≤B≤500,0≤A,KI,J≤1000 | 最小生成树的变形,需要额外加上一个点 0 0 0,然后把每个点都跟 0 0 0连上一条长度为 A A A的边,接着进行最小生成树。需要判断两点间的距离是否为 0 0 0,如果 K I , J = 0 K_{I,J}=0 KI,J=0,那么表示这两样东西之间不会导致优惠,则不连边。 | 55 |
树的直径
题目 | 题意 | 思路 | 代码 |
---|---|---|---|
核心城市 | 有一棵 n n n 个点的无权树,将 k k k 个点钦定为核心点,这 k k k 个点需满足以下两个条件:1. k k k 个点可以不经过点的情况下两两相互到达。2. 定义某个非核心点与这 k k k 个核心点的距离为,这个点与 k k k 个核心点的距离的最小值。那么所有非核心点中,与核心点的距离最大的点,其与核心点的距离最小。你需要求出这个最小值。 1 ≤ k < n ≤ 1 0 5 1 \le k < n \le 10 ^ 5 1≤k<n≤105。 | 首先求树的直径,方法为
2
2
2 次 dfs ,第一次从任意点出发,找到最远点,第二次从最远点出发,找到最远点的最远点,就是树的直径。接下来应该怎么做呢?不妨先画图:![]() ![]() | 56 |
树上倍增
题目 | 题意 | 思路 | 代码 |
---|---|---|---|
【模板】最近公共祖先(LCA) | 给定一棵有根多叉树,请求出指定两个点直接最近的公共祖先。点数,边数 ≤ 5 × 1 0 5 \le5\times 10^5 ≤5×105。 | 预处理出每个点向上 2 2 2 的幂次的点是多少,查询时两个点同时往上跳。 | 75 |
CF379F New Year Tree | 有一颗
4
4
4 个节点的树,
2
,
3
,
4
2,3,4
2,3,4 号节点的父亲节点都是
1
1
1。
m
m
m 次操作。操作有
1
1
1 种:1. u :设现在这颗树有
n
n
n 个节点,则您要新建两个节点
n
+
1
,
n
+
2
n+1,n+2
n+1,n+2 并让它们变为
u
u
u 的儿子节点(连一条
u
u
u 到
n
+
1
n+1
n+1 的边和
u
u
u 到
n
+
2
n+2
n+2 的边)。保证
u
u
u 是叶子节点。进行完操作后,您要输出此时树的直径。-
1
≤
m
≤
5
×
1
0
5
1\le m\le 5\times 10^5
1≤m≤5×105。 | 用
f
[
i
]
[
j
]
f[i][j]
f[i][j] 表示
i
i
i 点向上走
2
j
2^j
2j 步到达的点。首先初始化,当前直径是
2
2
2,
1
1
1 号节点深度
0
0
0,
2
,
3
,
4
2,3,4
2,3,4号节点深度
1
1
1,然后
f
[
2
]
[
0
]
,
f
[
3
]
[
0
]
,
f
[
4
]
[
0
]
f[2][0],f[3][0],f[4][0]
f[2][0],f[3][0],f[4][0] 都为
1
1
1。然后先把直径的两点设为
2
,
3
2,3
2,3。接下来添加点先把它们接起来,然后先求
A
A
A 和
U
U
U 的 LCA ,如果发现直径更新,替换
B
B
B,否则替换
A
A
A,则 len++ 。 | 57 |
CF29D Ant on the Tree | 给一棵树,根节点为
1
1
1,要求以特定顺序遍历这棵树的叶子节点,并顺序输出到达的每一个节点。如果做不到,输出 -1 。
3
≤
n
≤
300
3\le n\le 300
3≤n≤300 | 先把每个点的深度和父亲节点求好,然后计算叶子节点的个数,第
1
1
1 个叶子节点要特判,把它迭代到根,然后先打印出来,接着把下个叶子节点和上个叶子节点的深度差求出来,其中一个点迭代到相同层数,如果迭代的是前
1
1
1 个叶子节点,那么可以直接输出,否则存储下来,然后两个点一起往根的方向爬,如果路径是前
1
1
1 个点的直接输出,否则又存下来,然后把存下来的路径反过来存好,最后如果有重复的判掉,输出即可。可以使用 LCA 优化向上爬的过程。 | 58 |
闇の連鎖 | 给定 n n n 个节点的树(树上的边为主边)和 m m m 条 次边,求去掉 1 1 1 条主边和 1 1 1 条次边使图变为不连通的方案数。 1 ≤ n ≤ 1 0 5 , 1 ≤ m ≤ 2 × 1 0 5 1\le n\le 10^5,1\le m\le 2\times 10^5 1≤n≤105,1≤m≤2×105 | 先画一棵简单的树。![]() | 74 |
有向图的强连通分量
题目 | 题意 | 思路 | 代码 |
---|---|---|---|
[USACO03FALL / HAOI2006] 受欢迎的牛 G | 给定 n n n 个人和 m m m 条崇拜关系,崇拜具有传递性,问有多少人被所有人崇拜。 1 ≤ n ≤ 1 0 4 , 1 ≤ m ≤ 5 × 1 0 4 1\le n\le 10^4,1\le m\le 5\times 10^4 1≤n≤104,1≤m≤5×104。 | Kosaraju 算法的板子题。Kosaraju 算法用于缩点,具体步骤是这样的:1.建立原图、反向图,准备标记数组和栈各一个。2.对原图进行深度优先遍历,每个点return前把它压入栈。3.枚举每个点,如果这个点没有标记则标记,然后用反向图从这个点开始遍历,能遍历到的所有点跟这个点强连通。证明:按照深度优先遍历,最后压栈的一定比先压栈到达,所以如果在反向图中可达其他点,证明其他点可达此点,则强连通。接着缩点后,找出度为0的点,如果有多个答案为0,否则答案为这个强连通的所有点的个数。 | 59 |
学校网络 | 给定 n n n 个点 m m m 条边的有向图,求至少从几个点出发可以遍历到所有的点,最少添加几条边可以使得图变为强连通。 1 ≤ n ≤ 1 0 4 , 1 ≤ m ≤ 5 × 1 0 6 1\le n\le 10^4,1\le m\le5\times 10^6 1≤n≤104,1≤m≤5×106。 | 缩点之后跑拓扑,首先第一问明显问的是有多少个点入度为 0 0 0,而第二问则可以通过入度为 0 0 0 和出度为 0 0 0 的点连边的方式建立强连通,答案为入度为 0 0 0 和出度为 0 0 0 的点的个数中较大者。 | 76 |
[ZJOI2007]最大半连通子图 | 给定一个图,求它的最大半联通子图的点数和个数。点数 ≤ 1 0 5 \le 10^5 ≤105,边数 ≤ 1 0 6 \le 10^6 ≤106 | 先缩点,然后发现一条链上的强连通子图可以构成半连通子图,所以考虑做拓扑,求每个点的点数最多的链,然后统计数目。 | 77 |
[SCOI2011]糖果 | 给定 n n n 个数和 m m m 个数之间的关系( = , ≤ , ≥ , < , > =,\le,\ge,<,> =,≤,≥,<,>),求满足所有条件的数的和最小值。 | 差分约束建图,缩点在拓扑图上跑最长路。 | 78 |
无向图的双连通分量
题目 | 题意 | 思路 | 代码 |
---|---|---|---|
冗余路径 | 给定 n n n 个点 m m m 条边的无向连通图,求至少加几条边可以使得整个图变成双连通分量。 1 ≤ n ≤ 5000 , n − 1 ≤ m ≤ 1 0 4 1\le n\le 5000,n-1\le m\le 10^4 1≤n≤5000,n−1≤m≤104。 | 可以考虑把一个双连通分量中的点缩成一个,然后构成了一棵树,树上在叶节点之间互相连边可以构成环,设叶节点有 c n t cnt cnt 个,则答案为 ⌈ c n t 2 ⌉ \lceil \frac{cnt}{2}\rceil ⌈2cnt⌉。缩点方式:类似于有向图,区别在于需要判断 d f n u < l o w v dfn_u<low_v dfnu<lowv 为桥,然后弹栈操作缩点类比有向图 | 81 |
电力 | 给定一个由 n n n 个点 m m m 条边构成的无向图,请你求出该图删除一个点之后,连通块最多有多少。 1 ≤ n ≤ 1 0 4 , 1 ≤ m ≤ 1.5 × 1 0 4 1\le n\le 10^4,1\le m\le 1.5\times 10^4 1≤n≤104,1≤m≤1.5×104。 | 这里求的是割点,与桥的区别在于可以取到等于,然后此题求出每个点可以隔绝几个点,即有多少个子节点可以使得 d f n u ≤ l o w v dfn_u\le low_v dfnu≤lowv,如果不是根节点,要加上上面的部分。 | 82 |
矿场搭建 | 给定一个 m m m 条边的无向图,问要选择几个点和方案数,使得删去任意一点,分出的子图中任意一点可以到达选择的点。 m ≤ 500 m\le 500 m≤500。 | 可以考虑把每个点双连通分量当作一个点,和割点连边,然后如果这个点的度数为 0 0 0,那么它要建两个点,如果是 1 1 1,建一个,否则不建,方案数比较容易,乘法原理即可。 | 83 |
最短路
题目 | 题意 | 思路 | 代码 |
---|---|---|---|
AT218F | 给一个 n n n 个点 m m m 条边的无向图,问对于每一条边,将其去除后的最短路是多少。 2 ≤ n ≤ 400 , 1 ≤ m ≤ n ( n − 1 ) 2\le n\le 400,1\le m\le n(n-1) 2≤n≤400,1≤m≤n(n−1)。 | 因为删除的边如果不在 1 1 1 到 n n n的最短路上,则一定不会影响答案,如果在,则再跑一次最短路,跳过删除的边,这里的最短路边权都 = 1 =1 =1,所以可以用广搜,时间复杂度为 O ( n + m ) O(n+m) O(n+m),因为在最短路上的边不超过 n n n 条,所以总时间复杂度 O ( n ( n + m ) ) O(n(n+m)) O(n(n+m))。 | 60 |
二分图
题目 | 题意 | 思路 | 代码 |
---|---|---|---|
关押罪犯 | 给定一个 n n n 个点 m m m 条边的带权无向图,求将这些点分为两部分使得每部分中的边的权值的最大值最小。 n ≤ 2 × 1 0 4 , m ≤ 1 0 5 n\le 2\times 10^4,m\le 10^5 n≤2×104,m≤105 | 二分答案,然后将大于二分值的边加进去,判定一下是否是二分图。 | 88 |
棋盘覆盖 | 给定 n × n n\times n n×n 的棋盘,在上面放置 1 × 2 1\times 2 1×2 的骨牌,有 t t t 个格子是坏的,问最多可以放置多少骨牌。 1 ≤ n ≤ 100 , 0 ≤ t ≤ 100 1\le n\le 100,0\le t\le 100 1≤n≤100,0≤t≤100 | 首先放置骨牌可以看作连边,而每个点只能放置一次,所以是最大匹配,又因为可以将行列数之和的奇偶性不同的格子当作两个集合,所以本质上求的是二分图的最大匹配。 | 89 |
机器任务 | 有两台机器 A , B A,B A,B 以及 K K K 个任务。机器 A / B A/B A/B 有 0 ∼ N − 1 / 0 ∼ M − 1 0\sim N-1/0\sim M-1 0∼N−1/0∼M−1 种模式。最开始都处于模式 0 0 0。每个任务既可以在 A A A 上执行,也可以在 B B B 上执行。对于每个任务 i i i,如果该任务在 A / B A/B A/B 上执行,需要设置模式为 a i / b i a_i/b_i ai/bi,任务可以以任意顺序被执行,求机器模式转换总次数的最小值。 | 因为如果处于一个模式,那么肯定考虑将所有这个模式的任务完成,所以可以转换为一个最小点覆盖问题,而答案就是最大匹配数。 | 90 |
骑士共存问题 | 给定 n × n n\times n n×n 的棋盘,在上面放置骑士,有 t t t 个格子是坏的,问最多可以放置多少骑士,使得他们彼此之间没有攻击。 1 ≤ n ≤ 200 , 0 ≤ t < n 2 1\le n\le 200,0\le t<n^2 1≤n≤200,0≤t<n2。 | 这题和上一题特别像,这里求最大独立集,就是求总点数 − - − 最小独立集,注意还有减去不能使用的格子。 | 91 |
捉迷藏 | / | 求最小路径重复点覆盖,先做一遍传递闭包,然后求总点数 − - − 最大匹配 | 92 |
连通性
题目 | 题意 | 思路 | 代码 |
---|---|---|---|
AT219E | 给出一个 4 × 4 4×4 4×4 的 01 01 01 矩阵,有多少矩阵多边形可以包含所有 1 1 1。 | 考虑到每个格子只有围住和不围两种状态,则共有种围格子的方案,那如何判断是否合法呢?首先肯定要先判断有村庄的格子是否围住了,即检查的矩阵中为 1 1 1 的位置是否在方案中有,接下来是判断联通块,因为要围的是多边形,所以考虑另外建一个 17 17 17 点,这个点每次和在外围的点进行合并,围住的点内部合并,最后本质求的实际上是联通块的个数是否 = 2 =2 =2,可以用并查集来维护。时间复杂度 O ( 2 16 × 4 3 × α ( 17 ) ) O(2^{16}\times 4^3\times \alpha(17)) O(216×43×α(17))。 | 61 |
欧拉路径和欧拉回路
题目 | 题意 | 思路 | 代码 |
---|---|---|---|
铲雪车 | / | 考虑这里一条边要铲雪两次,所以看作有向图,这里每个点的入度等于出度,所以肯定是欧拉图,直接计算答案即可。 | 93 |
欧拉回路 | 给定一个有向/无向图,求它的一个欧拉回路。点数 ≤ 1 0 5 \le 10^5 ≤105,边数 ≤ 2 × 1 0 5 \le 2\times 10^5 ≤2×105 | 考虑 dfs ,遍历边时传引用,遍历完立刻删除,然后如果是无向图将反向边同时删除,然后在最后把这条边加入答案序列,最后逆序输出。 | 94 |
骑马修栅栏 | 求一个图的欧拉回路,保证有解,求字典序最小的方案。 | 容易发现由于记录是在最后进行的,所以考虑按照点的编号搜索,为了免除排序,使用邻接矩阵存储。 | 95 |
单词游戏 | 给定 n n n 个单词 s i s_i si,问是否能将他们排成一排,使得前一个单词最后一个字母是后一个单词的第一个字母。 1 ≤ n ≤ 1 0 5 , ∣ s i ∣ ≤ 1 0 3 1\le n\le 10^5,|s_i|\le 10^3 1≤n≤105,∣si∣≤103。 | 考虑直接将每个单词的首字母和尾字母连边,判断是否可以构成欧拉路径即可。 | 96 |
拓扑排序
题目 | 题意 | 思路 | 代码 |
---|---|---|---|
家谱树 | 给定一个图,求其拓扑排序 | 从所有入度为 0 0 0 的开始广搜,每搜一次入度 − 1 -1 −1,搜索序列就是拓扑排序。 | 97 |
可达性统计 | 一张 D A G DAG DAG,求每个点可以到达的点数。点数,边数 ≤ 30000 \le 30000 ≤30000 | 考虑用拓扑排序的你需进行递推,时间复杂度是
n
2
n^2
n2,空间也不够。考虑 bitset ,时间优化到
n
2
32
\frac{n^2}{32}
32n2。 | 98 |
车站分级 | / | 考虑每条线路,不在线路上的点的等级一定比在线路上的要低,可以考虑将每个不在线路上的点向在线路上的点连一条边,但是这样的边数可以达到 1 0 9 10^9 109,考虑可以在中间放置虚拟节点,使得建边一次优化到 O ( n ) O(n) O(n)。 | 99 |
树上启发式合并
题目 | 题意 | 思路 | 代码 |
---|---|---|---|
Lomsat gelral | 一棵大小为 n ≤ 1 0 5 n\le10^5 n≤105 根为的 1 1 1 树,每个点有一个颜色编号,求每个子树中颜色最多的所有颜色编号的总和。 | 考虑启发式合并,每次找出每个点的重儿子,将其他轻儿子用桶统计并清空,唯独重儿子加入不用清空。 | 102 |