图论
青烟绕指柔!
我不怕千万人阻挡,只怕自己投降。
展开
-
City Brain
题目链接:City Brain显然两条路径之间,相交的部分一定是一段连续的路径。所以我们可以枚举连续的路径,然后剩下4段不连续的路径。我们可以预处理两点之间的最短路,然后算出分别的和,然后三分即可。但是复杂度是 n * n * log 的。但是我们可以发现,对于枚举连续的相同长度的路径我们只需要知道4段不连续路径的最小值,然后复杂度就变成 n * n + n * log 了。AC代码:#pragma GCC optimize("-Ofast","-funroll-all-loops")#in原创 2021-07-04 13:16:33 · 369 阅读 · 0 评论 -
Commuter Pass
题目链接:Commuter Pass显然我们一定会走 s 到 t 的一条路径,正着走或者反着走。所以可以在最短路上dp,当前没走过上面的路径,正这正着走,正在反着走,已经走完了。4个状态的最短路。AC代码:#pragma GCC optimize("-Ofast","-funroll-all-loops")#include<bits/stdc++.h>#define int long longusing namespace std;const int N=1e5+10,M=4原创 2021-07-02 19:17:18 · 270 阅读 · 0 评论 -
佳佳的魔法药水
题目链接:佳佳的魔法药水看成一瓶药水要另一个药水的最短路,然后边权也是药水即可。因为要求方案数,所以我们更新的时候,保证作为边权的药水已经是最短的即可。然后要注意两瓶相同药水合成的情况。AC代码:#pragma GCC optimize("-Ofast","-funroll-all-loops")#include<bits/stdc++.h>//#define int long longusing namespace std;const int N=1010;int n,原创 2021-06-28 13:01:31 · 240 阅读 · 0 评论 -
最小 OR 路径
题目链接:最小 OR 路径显然我们可以得到最高位,然后根据贪心是合法的。然后根据得到的高位又可以往低位看,然后看最高的必须合法的位。AC代码:#pragma GCC optimize("-Ofast","-funroll-all-loops")#include<bits/stdc++.h>#define int long longusing namespace std;const int N=1e4+10,M=2e6+10;int n,m,s,t,res,ok,a[M],b原创 2021-03-08 20:21:25 · 167 阅读 · 0 评论 -
Telephone G
题目链接:Telephone G因为此题DP的时候,转移成环,所以我们可以考虑最短路模型。我们对于这种绝对值距离,我们可以想到对相邻点建边权为1的边来解决。但是考虑种类问题。我们可以建立分层图,第0层为原图,第 1->k 层代表每种颜色,相邻边权为1,然后如果颜色相同则可以到达原图。最后因为边权只有0和1,01BFS即可。AC代码:#pragma GCC optimize("-Ofast","-funroll-all-loops")#include<bits/stdc++.h&g原创 2021-01-30 16:55:23 · 157 阅读 · 0 评论 -
Codeforces - Catowice City
题目链接:Codeforces - Catowice City因为同一个人和猫我们不能同时选。所以我们可以看成一个点。我们对于一条边的含义:u -> v 表示如果选 u 就不能选 v。我们可以发现对于一个scc,我们只能选人或者猫。所以如果只有一个scc,则为 No。否则我们拿一个出度为0的scc选人即可。AC代码:#pragma GCC optimize("-Ofast","-funroll-all-loops")#include<bits/stdc++.h>//#原创 2021-01-21 14:17:13 · 192 阅读 · 0 评论 -
[JLOI2015]管道连接
题目链接:[JLOI2015]管道连接我们先对每个特殊点集求出构成一颗斯坦纳树的最小代价。然后对于答案来说,是一颗最小代价的斯坦纳森林。所以我们最后枚举每种集合的斯坦纳树来组合成斯坦纳森林即可。要注意转移的合法性。当前集合要被拆分成几颗不同频率的生成树,并且这些频率的点被全部包含才可以转移。AC代码:#pragma GCC optimize("-Ofast","-funroll-all-loops")#include<bits/stdc++.h>//#define int lon原创 2021-01-18 14:54:34 · 237 阅读 · 0 评论 -
Codeforces - Strange Set
题目链接:Codeforces - Strange Set不难看出是一个最大权闭合子图。但是我们考虑优化连边,显然每个点对于同一种权值来说,只会连前面最近的。AC代码:#pragma GCC optimize("-Ofast","-funroll-all-loops")#include<bits/stdc++.h>//#define int long longusing namespace std;const int inf=0x3f3f3f3f;const int N=3原创 2021-01-16 18:55:17 · 290 阅读 · 4 评论 -
Codeforces - E. Minimum Path
题目链接:Codeforces - E. Minimum Path不难发现其实就是最大边权变成0,最小边权变成2倍。我们可以假设是可以有一条边免费走,且有一条边要走2倍的一个最短路。其实就是一个分层图或者最短路上dp。AC代码:#pragma GCC optimize("-Ofast","-funroll-all-loops")#include<bits/stdc++.h>#define int long longusing namespace std;const int N原创 2021-01-16 14:42:06 · 191 阅读 · 0 评论 -
[PA2010]Riddle
题目链接:[PA2010]Riddle不难看出可以使用2-SAT去解决。对于每条边来说,相当于就是某个端点不取,另一个端点必须取。对于每个集合来说,我们就是如果这个点取,那么其他点不能取。但是不能暴力连边。我们可以如下建图:1 < 2 < 3 < 4 < 5 …1 > 2 > 3 > 4 > 5 …分别加上两排点,然后对于某个点取,往前后位置连边即可。因为数据比较大,边很多,所以用vector建图会TLE。pushback次数太多。AC代原创 2020-12-15 19:56:06 · 245 阅读 · 0 评论 -
Codeforces - Yet Another DAG Problem
题目链接:Codeforces - Yet Another DAG Problem因为每个边有一个权值为 (a[u] - a[v])*w,于是我们可以把边拆开,看每个点的贡献。我们可以发现我们对每个点设置 0 -> n-1 的权值一定可以达到最小值。然后对每个点可以建立一个类似于分层图的东西,每条边代表 0 ,1,2,。。。然后对于每个点是否选取也就是这条边是否割掉。然后对于DAG上面的权值大小影响,我们可以对 v 的权值小的点,连向 u 的权值大的点,流量为 INF ,这样就能保证最小割原创 2020-11-29 22:01:25 · 322 阅读 · 0 评论 -
老奶奶参加宴会
题目链接:老奶奶参加宴会对于新加的边,显然不能n*n的复杂度去加,我们可以对值排序,然后相邻点连接即可。AC代码:#pragma GCC optimize("-Ofast","-funroll-all-loops")#include<bits/stdc++.h>#define int long longusing namespace std;const int N=3e5+10,M=N*5;int n,m,a[N],s,t,id[N],vis[N],d[N],p[N];in原创 2020-11-25 18:07:02 · 294 阅读 · 0 评论 -
旅游胜地
题目链接:旅游胜地显然可以二分最小值。然后对于一个点取某个值的时候,对于相邻的点我们有能选或者不能一起选,直接2-SAT即可。AC代码:#pragma GCC optimize("-Ofast","-funroll-all-loops")#include<bits/stdc++.h>//#define int long longusing namespace std;const int N=2e5+10;int n,m,a[N],b[N],dfn[N],low[N],cnt原创 2020-11-23 20:47:57 · 200 阅读 · 2 评论 -
线性探查法
题目链接:线性探查法考虑每个值,如果不在本来的位置上,那么一定是之前的位置被填充了,然后我们可以根据当前的位置,和本来的位置推出一个在他之前被填充的区间。然后做一个最小字典序拓扑排序即可。不过对于区间连边是 O(n*n)的,需要线段树优化建图。AC代码:#pragma GCC optimize("-Ofast","-funroll-all-loops")#include<bits/stdc++.h>//#define int long longusing namespace s原创 2020-11-16 18:40:28 · 1703 阅读 · 0 评论 -
爬爬爬山
题目链接:爬爬爬山显然能够到达的最高地方为 a[1] + k ,然后大于的都需要降低到 a[1] + k ,因为上下是可以抵消的。所以每次和 a[1] + k 判断即可。AC代码:#pragma GCC optimize("-Ofast","-funroll-all-loops")#include<bits/stdc++.h>#define int long longusing namespace std;const int N=2e5+10,M=N*2;int n,m,a[原创 2020-11-15 20:22:52 · 115 阅读 · 0 评论 -
Codeforces - Graph Transpositions
题目链接:Codeforces - Graph Transpositions显然如果改变的次数很多的话,那么我们一定是改变的次数越少越好。如果改变次数很少才可能是 用多改变几次,然后少走一些距离。然后判一下最小的改变次数即可。并且求出在最小改变次数下的最小距离。如果改变次数很小直接dp即可。AC代码:#pragma GCC optimize("-Ofast","-funroll-all-loops")#include<bits/stdc++.h>//#define int l原创 2020-11-03 20:59:54 · 270 阅读 · 0 评论 -
[TJOI2018]智力竞赛
题目链接:[TJOI2018]智力竞赛首先我们可以想到二分。然后对于需要覆盖的点,看是否被小于等于 n+1 条链全部覆盖,先跑一个传递闭包,然后把小于等于二分的点拿出来建图即可。然后就是一个最小链覆盖了。如果不跑传递闭包,单独对 x+m -> x的边,我们无法处理 3 -> 5 -> 4 ,但是我们二分的答案为4的情况。AC代码:#pragma GCC optimize("-Ofast","-funroll-all-loops")#include<bits/stdc原创 2020-10-15 14:48:57 · 219 阅读 · 0 评论 -
健康监测计划
题目链接:健康监测计划显然从叶子贪心是最优的。于是我们可以想到先取叶子,然后把叶子删掉,然后继续取叶子。一共取 k/2 次叶子,如果k是奇数,最后再任意取一个点即可。所以我们树上拓扑即可。AC代码:#pragma GCC optimize("-Ofast","-funroll-all-loops")#include<bits/stdc++.h>//#define int long longusing namespace std;const int N=1e6+10;int原创 2020-09-27 10:52:06 · 960 阅读 · 0 评论 -
Splatter Painting
题目链接:Splatter Painting因为距离很小。所以,我们可以逆向操作,当前仅当这个点未被染色才去递归子节点。然后如果枚举到这个点,之前一个到过的节点还能到的距离大于当前还能到的距离就return;复杂度为 d*(n+m)AC代码:#pragma GCC optimize("-Ofast","-funroll-all-loops")#include<bits/stdc++.h>//#define int long longusing namespace std;c原创 2020-09-07 23:01:22 · 233 阅读 · 0 评论 -
Codeforces - Buying Sets
题目链接:Codeforces - Buying Sets如果不考虑 k 的限制,那么就是一个最小权闭合子图。然后现在需要相等,所以我们给集合一个正的权值,元素一个负的权值,保证可以相等。AC代码:#pragma GCC optimize("-Ofast","-funroll-all-loops")#include<bits/stdc++.h>#define int long longusing namespace std;const int inf=0x3f3f3f3f3f原创 2020-08-31 17:45:48 · 261 阅读 · 0 评论 -
[COI2012] TRAMPOLIN
题目链接:[COI2012] TRAMPOLIN建立一个传送点,然后变成某个点开始的种类最长路。但是存在环,所以我们可以缩点。然后记忆化dfs或者拓扑即可。AC代码:#pragma GCC optimize("-Ofast","-funroll-all-loops")#include<bits/stdc++.h>//#define int long longusing namespace std;const int N=3e5+10;int n,k,h[N],dfn[N],原创 2020-08-29 15:15:56 · 203 阅读 · 0 评论 -
[JSOI2009]球队收益
题目链接:[JSOI2009]球队收益因为要限制每个比赛,一胜一负,流量无法限制。所以我们可以假设先全败,然后选择某个人获胜,然后用差值来改变。假设当前a胜,b负。然后获胜一次的差值为:c*(a+1)*(a+1) + d*(b-1)*(b-1) - c*a*a - d*b*b= c*(2*a+1) - d*(2*b-1)AC代码:#pragma GCC optimize("-Ofast","-funroll-all-loops")#include<bits/stdc++.h&g原创 2020-08-25 00:19:51 · 119 阅读 · 0 评论 -
URAL - 1742
题目链接:URAL - 1742显然,最小次数就是入度为0的点+单独环的个数。最多的个数就是:每个环只能贡献一次,答案就为n - 所有环的大小 + 环的个数。我们直接DFS找环即可。AC代码:#pragma GCC optimize("-Ofast","-funroll-all-loops")#include<bits/stdc++.h>//#define int long longusing namespace std;const int N=1e5+10;int n,原创 2020-08-22 22:59:36 · 170 阅读 · 0 评论 -
URAL - 1651
题目链接:URAL - 1651因为边有访问顺序,所以我们可以采用动态加边的方式。也就是按照顺序枚举每一条边,是否会更新下一个点。但是注意我们要输出方案,所以我们应该是对每个编号存上一个转移点的位置。AC代码:#pragma GCC optimize("-Ofast","-funroll-all-loops")#include<bits/stdc++.h>//#define int long longusing namespace std;const int N=1e5+1原创 2020-08-22 22:04:44 · 208 阅读 · 0 评论 -
Flags
题目链接:Flags首先这个可以二分。然后这个东西可以 2-SAT,然后我们可以发现我们对每个点连边的时候连的是一个区间。所以我们可以用线段树优化。如果对每个点都建立选 or 不选两个点的话,我们就需要两颗线段树了。我们可以优化一下,对于一个点选的话,我们找到这个区间不能选的点,然后就是连向这个区间所有点的另一个点,也就是选这个点,那么必须选这个区间的另一个点。然后找区间的时候,不能连向自己的反点。AC代码:#pragma GCC optimize("-Ofast","-funroll-al原创 2020-08-21 22:14:26 · 409 阅读 · 0 评论 -
HDU - 5352
题目链接:HDU - 5352按照每次的变换建边即可。因为要求最小字典序,所以我们可以用费用流的权值来限制。AC代码:#pragma GCC optimize("-Ofast","-funroll-all-loops")#include<bits/stdc++.h>//#define int long longusing namespace std;const int inf=0x3f3f3f3f;const int N=1e3+10,M=1e6+10;int n,m,k,原创 2020-08-20 22:59:33 · 146 阅读 · 0 评论 -
乔乔和牛牛逛超市
题目链接:乔乔和牛牛逛超市因为一个物品是有两种状态的。A,B。买了A才能在买A的基础上买B。我们可以把费用拆成两种。第一个为f(A),第二个为f(B)-f(A)。这样的话买两个的时候就不会多算了。然后按照最大权闭合子图建图即可。AC代码:#pragma GCC optimize("-Ofast","-funroll-all-loops")#include<bits/stdc++.h>#define int long longusing namespace std;cons原创 2020-08-18 23:19:47 · 1323 阅读 · 0 评论 -
URAL - 1487
题目链接:URAL - 1487这个题目说的不是很清楚,如果一个队A比另一个队B强的定义是:不比能打过B的若。也就是说,不存在一个队即能打过A,也能打过B。这个我们可以先维护每个点打不过的点,然后传递闭包得到所有打得过自己的点。这里可以Bitset优化。然后查询的时候直接就是两个bitset与的个数。AC代码:#pragma GCC optimize("-Ofast","-funroll-all-loops")#include<bits/stdc++.h>//#define原创 2020-08-17 21:50:28 · 162 阅读 · 0 评论 -
HDU - 5215
题目链接:HDU - 5215对于奇环来说,直接二分图染色即可。对于偶环来说,我们先DCC缩点。然后对于一个DCC来说,如果点数为偶数那么必然存在一个偶环。如果点数为奇数,如果边数不为点数,那么证明有多个环嵌套,如果是两个奇环那么一定可以抵消成偶环。AC代码:#pragma GCC optimize("-Ofast","-funroll-all-loops")#include<bits/stdc++.h>//#define int long longusing namespac原创 2020-08-15 23:42:15 · 241 阅读 · 0 评论 -
HDU - 5325
题目链接:HDU - 5325显然,我们从权值小的连向权值大的。那么答案就是每个点能到的点数。取max。只有这样,一个联通块才是合法的。保证一定是小的在中间。AC代码:#pragma GCC optimize("-Ofast","-funroll-all-loops")#include<bits/stdc++.h>//#define int long longusing namespace std;const int N=5e5+10;int n,w[N],dp[N],re原创 2020-08-15 16:25:28 · 159 阅读 · 0 评论 -
牛客练习赛67
题目链接:牛客练习赛67A:模拟,注意全0的情况。#pragma GCC optimize("-Ofast","-funroll-all-loops")#include<bits/stdc++.h>//#define int long longusing namespace std;string str;int ch(char c){return c<'0'||c>'9';}void solve(){ int ok=0,st=0;; for(int i=0;i&原创 2020-08-14 22:48:50 · 206 阅读 · 0 评论 -
「SNOI2017」炸弹
题目链接:「SNOI2017」炸弹因为每个点能到的区间是已知的。所以我们相当于可以是一个点对能到的所有点连边。然后对一个点求出能到的点的最小值和最大值。然后做差就能找到能到的点的个数。所以缩点之后拓扑排序即可。AC代码:#pragma GCC optimize("-Ofast","-funroll-all-loops")#include<bits/stdc++.h>#define int long longusing namespace std;const int N=2e原创 2020-08-14 14:46:24 · 169 阅读 · 0 评论 -
HDU - 5418
题目链接:HDU - 5418状态dp,dp[i][s]为当前在 i 点,然后经过的状态为 s 的最短路。然后Dijkstra即可。AC代码:#pragma GCC optimize("-Ofast","-funroll-all-loops")#include<bits/stdc++.h>//#define int long longusing namespace std;const int N=17;int n,m,g[N][N],dp[N][1<<N],vis原创 2020-08-14 00:13:58 · 241 阅读 · 0 评论 -
HDU - 5669
题目链接:HDU - 5669区间之间连边用线段树或者倍增优化即可。然后k次机会可以建立分层图,或者直接dp。AC代码:#pragma GCC optimize("-Ofast","-funroll-all-loops")#include<bits/stdc++.h>//#define int long longusing namespace std;const int N=5e5+10,M=4e6+10;int n,m,k,d[N][15],vis[N][15],res,原创 2020-08-12 12:51:57 · 211 阅读 · 0 评论 -
HDU - 6290
题目链接:HDU - 6290对判断是否能走,我们可以发现等级越低,越能过去。然后判断消费:假设每次经过的边的等级提升值分别为:a1,a2,a3…ak我们可以发现代价为:log2(1+a1+a2+a3+…+ak),也是等级越低越优,所以我们对等级跑最短路即可。AC代码:#pragma GCC optimize("-Ofast","-funroll-all-loops")#include<bits/stdc++.h>#define int long longusing name原创 2020-08-04 11:50:43 · 198 阅读 · 0 评论 -
HDU - 6252
题目链接:HDU - 6252可以发现,给出的信息其实就是几个点之间的大小关系,建差分约束系统即可。AC代码:#pragma GCC optimize("-Ofast","-funroll-all-loops")#include<bits/stdc++.h>#define int long longusing namespace std;const int N=2e4+10,M=N*10;int n,m,x,d[N],cnt[N],ts,vis[N];int head[N]原创 2020-08-04 10:27:52 · 248 阅读 · 0 评论 -
Codeforces - Captain Flint and Treasure
题目链接:Codeforces - Captain Flint and Treasure如果不是输出路径的话,显然就是DAG上面dp。现在需要输出路径,我们就要知道选的先后顺序。然后每个点就看之前的点贡献的正负,确定先后顺序,然后又是一个拓扑排序了。AC代码:#pragma GCC optimize("-Ofast","-funroll-all-loops")#include<bits/stdc++.h>#define int long longusing namespace原创 2020-07-31 23:11:30 · 260 阅读 · 0 评论 -
HDU - 6437
题目链接:HDU - 6437其他博客中基本上都是O(n+m*m)复杂度的连边。但是其实可以优化到O(n+m)我们对每种种类,分别看成两层图,然后第一种是第一类的,第二层是第二类的。如果选择某个节目,那么看完之后连向本身的下一个点则 -W 的费用,否则连向另一层点为 0 的费用。AC代码:#pragma GCC optimize("-Ofast","-funroll-all-loops")#include<bits/stdc++.h>//#define int long lon原创 2020-07-31 21:39:38 · 244 阅读 · 0 评论 -
地铁
题目链接:地铁因为对点跑最短路很难判断是否是同一条地铁转移而来, 所以我们可以对边跑最短路。AC代码:#pragma GCC optimize("-Ofast","-funroll-all-loops")#include<bits/stdc++.h>#define int long longusing namespace std;const int N=1e5+10,M=N<<2;int n,m,d[M],res;int head[N],nex[M],to[M]原创 2020-07-24 18:01:32 · 269 阅读 · 0 评论 -
Dynamic Graph
题目链接:Dynamic Graph很简单的一道题,但是要注意细节。更新的时候暴力更新就好了,然后拓扑上面维护Bitset,但是要注意黑点不能直接跳过,直接不去更新颜色即可,如果直接跳过会导致某些点加不进来。AC代码:#pragma GCC optimize("-Ofast","-funroll-all-loops")#include<bits/stdc++.h>//#define int long longusing namespace std;const int N=31原创 2020-07-24 15:17:34 · 854 阅读 · 0 评论