拓扑排序
酷酷的Herio
这个作者很懒,什么都没留下…
展开
-
P3119 [USACO15JAN]Grass Cownoisseur G(tarjan&spfa)
P3119 [USACO15JAN]Grass Cownoisseur G(tarjan&spfa) 题意 给定有向图和至多一次逆向操作,求从1出发到回到1最多经过不同的点数。 思路 显然先tarjan缩点,不使用操作的答案即:1所在的强连通分量大小。 使用一次逆向操作,考虑对缩点后的图跑最长路,分别求以111为起点的最长路和以111为终点的最长路。 然后对于某个有向边edge(u,v)edge(u,v)edge(u,v) 答案就是:d1(v)+d1(u)−c[bl[1]]d_1(v)+d_1(u)原创 2021-08-23 12:43:42 · 267 阅读 · 0 评论 -
1719. 重构一棵树的方案数(拓扑排序&猜结论)
1719. 重构一棵树的方案数(拓扑排序&猜结论) 1.我们记每个点在pairspairspairs中出现的次数为degdegdeg,祖先一定比儿子的度数要大。 2.因此我们可以拓扑排序所有出现过的点,然后从小到大找,对于当前结点iii,我们往后找到第一个与他相连的结点,这个结点jjj就是它的直接祖先,如果他们两的度数相同说明这两个点等价,因此有根树有多种,而且还有判断,对于所有与iii相连的结点 肯定也必须与jjj相连才行。 const int N=505; #define pb push_b原创 2021-01-11 18:40:51 · 423 阅读 · 0 评论 -
LC.207.课程表(拓扑排序)
LC.207.课程表(拓扑排序) 思路:拓扑排序。 1.dfsdfsdfs解法: class Solution { public: vector<vector<int> >e; vector<int>vis;//(0:未搜的点 1:正在搜的点 2:已经搜完的点) bool ok; void dfs(int u){ vis[u]=1; for(int v:e[u]){ if(!vis[v原创 2020-08-04 08:44:48 · 447 阅读 · 0 评论 -
LC.329.矩阵中的最长递增路径(记忆化搜索)
LC.329.矩阵中的最长递增路径(记忆化搜索) 思路: 1.记忆化搜索,这个实现思路很简单,具体看代码。 int d[4][2]={0,1,0,-1,1,0,-1,0},vis[500][500]; class Solution { public: vector<vector<int> >dp,a; int mx,n,m; int dfs(int x,int y){ if(dp[x][y]) return dp[x][y];原创 2020-07-26 11:00:41 · 382 阅读 · 0 评论 -
P3181 [HAOI2016]找相同字符(广义SAM)
P3181 [HAOI2016]找相同字符(广义SAM) 思路: 求出两个字符串的endposendposendpos集合sz[np][0],sz[np][1]sz[np][0],sz[np][1]sz[np][0],sz[np][1]。 然后利用乘法原理:ans+=sz[p][0]×sz[p][1]×(len[p]−len[fa[p]])ans+=sz[p][0]\times sz[p][1]\times (len[p]-len[fa[p]])ans+=sz[p][0]×sz[p][1]×(len[p]−原创 2020-07-22 09:44:44 · 312 阅读 · 0 评论 -
F. Removing Leaves(拓扑排序)
F. Removing Leaves(拓扑排序) 图论wslwslwsl。 思路:考虑类比拓扑排序,将叶子结点入队,然后对其相邻结点遍历,当被遍历次数到达kkk次,ans++ans++ans++,如果此时度数为111就入队,注意需要用visvisvis数组标记一下那些结点已经入过队,且标记时需要在queuequeuequeue,一次标记一个,因为存在edge(u,v)edge(u,v)edge(u,v),这样的情况,度数都是111,但是如果都标记了,就算不了贡献了。 时间复杂度:O(n+m)O(n+m)O(原创 2020-07-21 08:56:09 · 527 阅读 · 1 评论 -
E. Directing Edges(拓扑排序)
E. Directing Edges(拓扑排序) 思路:拓扑排序。 考虑只由有向边组成的图。 显然若该图有环显然无解。 否则必然有解。 因为:该有向图是一个DAGDAGDAG能构成一个拓扑序,假设当前我们有一条无向边从拓扑序尾连向拓扑序首,显然我们可以该边该边的方向:即让拓扑序较小的点指向拓扑序较大的点,这样就不会破坏原有的拓扑序,使得该图仍为DAGDAGDAG。 #include<bits/stdc++.h> using namespace std; typedef long long ll;原创 2020-07-19 21:01:24 · 860 阅读 · 0 评论 -
P3243 [HNOI2015]菜肴制作(拓扑排序&反图)
P3243 [HNOI2015]菜肴制作(拓扑排序&反图) 传送门 思路:因为题意是要在满足限制的情况下,让数字的小的在前,注意不是字典序最小,ep:1,2,3,4(2,4),(3,1)ep:1,2,3,4 (2,4),(3,1)ep:1,2,3,4(2,4),(3,1)显然如果字典序最小答案就是2,3,1,42,3,1,42,3,1,4.但是答案应该是3,1,2,43,1,2,43,1,2,4。因为首先要满足111在前面。所以考虑让后面的数尽可能大,这样才能为前面腾出更多空间,要优先满足最小的条件原创 2020-05-26 13:05:08 · 443 阅读 · 0 评论 -
P1983 车站分级(拓扑排序)
P1983 车站分级(拓扑排序) 传送门 思路 :将每个车次车站的关系抽象化为边的关系,不停靠的车站等级肯定比停靠的车站等级低,因此可以建立一条边,然后就用拓扑排序搞搞就行了,注意判断重边。 #include<bits/stdc++.h> using namespace std; typedef long long ll; const int N=1e3+5; #define mst(a) memset(a,0,sizeof a) int n,m,in[N],vis[N],a[N]; bool原创 2020-05-26 11:50:58 · 492 阅读 · 0 评论 -
P1137 旅行计划(拓扑排序&dp)
P1137 旅行计划(拓扑排序&dp) 传送门 思路:显然是用拓扑排序,又因为要记录以每个结点为终点的拓扑排序最大结点数,显然可以用一个简单dpdpdp转移实现。 即:dp[v]=max(dp[v],dp[u]+1)dp[v]=max(dp[v],dp[u]+1)dp[v]=max(dp[v],dp[u]+1)。 然后随便搞搞就出来了。 时间复杂度:O(n+m)O(n+m)O(n+m) AC代码: #include<bits/stdc++.h> using namespace std;原创 2020-05-26 09:14:50 · 388 阅读 · 0 评论 -
P1038 神经网络(拓扑排序)
P1038 神经网络(拓扑排序) 思路:一道拓扑排序经典题,此题要求算出最后所有的结点c[i]c[i]c[i]。 一开始c[i]>0c[i]>0c[i]>0的点被认为是输入层,即入度为0的点。然后用拓扑排序对相邻结点不但操作即可,输出层即出度为0的点。最后从111到nnn遍历判断该结点是否满足!out[i]&&c[i]>0!out[i]\& \&c[i]>0!out[i]&&c[i]>0即可。这里out[i]out[i]ou原创 2020-05-26 09:03:24 · 399 阅读 · 0 评论 -
P4017 最大食物链计数(拓扑排序+简单dp)
P4017 最大食物链计数(拓扑排序+简单dp) 传送门 思路:拓扑排序+简单dpdpdp。显然每个最大食物链起点为是入度为0的点,终点是出度为0的点,这样我们只需要统计每个出度为0的点的最大食物链贡献,最后求和。 设ans[i]ans[i]ans[i]为从所有入度为0点到达该点的路径数。 显然对于相连边有转移方程:ans[v]+=ans[u]ans[v]+=ans[u]ans[v]+=ans[u] 时间复杂度:O(n+m)O(n+m)O(n+m) AC代码: #include<bits/stdc++原创 2020-05-25 18:16:57 · 465 阅读 · 0 评论 -
烦人的依赖(拓扑排序)
烦人的依赖(拓扑排序) 传送门 思路:拓扑排序,因为要满足最小字典序,所以可以用优先队列进行实现。先将每个字符串转换为一个结点,这里用哈希表即可,然后将每个结点的边也进行排序,最后用拓扑排序的板子即可。 AC代码: #include<bits/stdc++.h> using namespace std; typedef long long ll; const int N=3e4+10; #define mst(a) memset(a,0,sizeof a) string s[N]; int an原创 2020-05-23 18:37:33 · 502 阅读 · 0 评论