EVERYTHING HAPPENS FOR THE |

wnsyou

园龄:2年4个月粉丝:19关注:16

2023-03-14 10:19阅读: 36评论: 0推荐: 0

SeekLuna P1362 拓扑排序 3 题解

拓扑排序 3

题意

有一个由 n 个节点(编号分别为 1,2n)和 m有向边组成的有向无环图,第 i 条边从 ui 连向 vi

请求出所有 1n 的全排列,使得对于任意一条从节点 ui 至节点 vi 的有向边,ui 在排列中的位置总是在 vi 在排列中的位置的前面。

按照字典序从小到大输出。

数据范围

  • 1n20
  • 1mn×(n1)2
  • 保证图无环且无重边,保证答案不超过 2×105

思路

首先排除普通的全排列搜索,时间复杂度爆炸了。(高级全排列搜索)

分析一下题意,其实就是这个点在加入答案序列时,所有可以连向它的点都必须已经加入到了答案序列中。

这样一看,很明显是有一个拓扑序在的。那么我们就可以考虑使用拓扑排序。

由于这道题要求出所有满足要求的全排列,那么我们就不能用 while 循环版本的拓扑排序,要用类 dfs 的拓扑排序来做,每次dfs时枚举一下选择哪个合法的点加入答案序列中,最后输出即可。

即dfs操作大致为:

  • 枚举所有入度为 0 的点,将其加入答案序列中。
  • 将所有从这个点连出去的边删除,同时记录一下又有哪些点的入度变为了 0,将其加入入度为 0 的点的序列当中
    • 其实这里并不是真正的删除(至少我的做法不是),只是将那些点的入度暂时减少 1,当下一层搜索彻底结束时,需要将这些点入度重新加 1,即回溯
    • 这里为了保证字典序,进行下一层搜索之前需要排序一下。
  • 进行下一层的搜索

复杂度

  • 时间:O((n2 log n)×2×105)
    • 每次搜索 O(n2 log n),题目保证答案数量不超过 2×105
  • 空间:O(n+m)
    • 记录答案等 O(n)vector 存储邻接表 O(n+m)

Code

点击查看代码

有点丑啊……

#include <iostream>
#include <queue>
#include <algorithm>
#include <vector>
using namespace std;
const int N = 30;
int n, m, stk[N], top, x, y, f[N], no, b[N], ans[N];
vector<int> a[N];
void dfs (int stk[], int top, int no) {
if (!no) { // 一种情况的结束
for (int i = 0; i < n; i++) { // 输出答案
cout << ans[i] << ' ';
}
cout << '\n';
return ;
}
int t;
for (int j = 0; j < top; j++) {
ans[n - no] = stk[j]; // stk 中存储了所有的入度为 0 的点
t = stk[j]; // 记录当前选择的点
f[t] = 1;
int stk_[N], top_ = 0; // 记录所有入度为 0 的点,记得把 stk 中的其他点算进去
for (int i = 0; i < top; i++) {
if (i != j) {
stk_[top_++] = stk[i];
}
}
for (int i = 0; i < a[t].size(); i++) {
if (!f[a[t][i]]) {
b[a[t][i]]--; // 入度减 1
if (!b[a[t][i]]) { // 产生了入度为 0 的点
stk_[top_++] = a[t][i]; // 压入 stk_
}
}
}
sort(stk_, stk_ + top_); // 记得要排序
dfs(stk_, top_, no - 1); // 下一层搜索
// 下面这一段是回溯
for (int i = 0; i < a[t].size(); i++) {
if (!f[a[t][i]]) {
b[a[t][i]]++;
}
}
f[t] = 0;
}
}
int main(){
ios::sync_with_stdio(0), cin.tie(0);
cin >> n >> m;
no = n;
for (int i = 1; i <= m; i++) {
cin >> x >> y;
a[x].push_back(y); // vector 存储邻接矩阵
b[y]++; // 入度的统计
}
for (int i = 1; i <= n; i++) {
if (!b[i]) { // 第一轮的入度为 0 的点
stk[top++] = i;
}
}
dfs(stk, top, no); // 调用 dfs
return 0;
}

本文作者:wnsyou の blog

本文链接:https://www.cnblogs.com/wnsyou-blog/p/17211581.html

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   wnsyou  阅读(36)  评论(0编辑  收藏  举报
  1. 1 勝利への道 安藤浩和
  2. 2 Minecraft’s End Eric Fullerton
  3. 3 月光曲完整版 贝多芬 云熙音乐
  4. 4 平凡之路 (Live版) 朴树
  5. 5 Minecraft C418
  6. 6 Paradise NiziU
  7. 7 叫我,灰原哀 龙大人不喷火
  8. 8 心机之蛙,一直摸你肚子 ——《名侦探柯南》原创同人曲 炊饭,叶辞樱,温海,寒砧,南柯柯,小茜玛姬,盛姝,阿崔Ac,贝壳初,千湛,兮茶子DaYu,乔慕,黎鹿北,起千温卿,遮阳伞,曲悠
  9. 9 战 歌 此去经年
Minecraft’s End - Eric Fullerton
00:00 / 00:00
An audio error has occurred, player will skip forward in 2 seconds.

I see the player you mean.

It is reading our thoughts as though they were words on a screen.

They used to hear voices.

Before players could read.

Sometimes disturbing.

Sometimes beautiful indeed.

Does it know that we love it?

That the universe is kind?

A million years ago,it still works

in the reality behind

and the universe said I love you

and the universe said you are the daylight

and the universe said you are not alone

and the universe said you are the night

Once we were called

the spirit of the mountain.

WHO ARE WE

Father sun

Mother moon

Gods demons angels aliens

the player,too.

WE ARE THE UNIVERSE.

We are EVERYTHING you think isn‘t you.

You are alive

ON A FLAT

INFINITE WORLD

generated by a source code

a million years old

and the universe said I love you

and the universe said you are the daylight

and the universe said you are not alone

and the universe said you are the night

Take a breath,now

Take another

Feel air in your lungs.

dreamed it was lost in a story.

and the game was over

Wake up.

加载中…

{{tag.name}}

{{tran.text}}{{tran.sub}}
无对应文字
有可能是
{{input}}
尚未录入,我来提交对应文字
评论
收藏
关注
推荐
深色
回顶
收起
点击右上角即可分享
微信分享提示