[拓扑排序] aw3696. 构造有向无环图(拓扑排序+memset使用坑点+aw周赛004_3)
Posted Ypuyu
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[拓扑排序] aw3696. 构造有向无环图(拓扑排序+memset使用坑点+aw周赛004_3)相关的知识,希望对你有一定的参考价值。
1. 题目来源
相关链接:
2. 题目解析
好题,DAG
与拓扑排序。
先考虑有向边,如果有向边都存在环的话,由于我们不能更改其方向,所以必然存在环,则一定出错。
若有向边考虑完毕后没环的话,那么可以将拓扑序写出来,将无向边从前往后赋予方向即可,一定可以构造出来拓扑序。
本题不保证给定的图是连通的,在处理中没啥影响。
h[N]
作为头数组,会用到 1~n
这些下标,故在 memset
的时候是要初始化 n+1
个。 同理 d[n]
这个也是一个坑点…
细节:
- 注意不要直接使用
memset
,因为T
是2e5
的,外部数组大小也是2e5
的,memset
的时间是线性的,需要两次memset
,但是即便这样时间复杂度也到达了2e5*2*2e5=8e10
的恐怖复杂度,回过,但特别容易被卡常数。 - 循环初始化就行了,但是注意要初始化
n+1
个。
时间复杂度: O ( n + m ) O(n+m) O(n+m)
空间复杂度: O ( n ) O(n) O(n)
#include <bits/stdc++.h>
using namespace std;
const int N = 2e5+5, M = 2e5+5;
int n, m, k; // k 用来记录无向边的个数
int h[N], e[M], ne[M], idx;
int d[N]; // 统计入度
struct Edge {
int a, b;
} edges[M]; // 存无向边
int q[N], pos[N]; // 队列,存储队列中拓扑排序各点的下标
void add(int a, int b) {
e[idx] = b, ne[idx] = h[a], h[a] = idx ++ ;
}
bool topsort() {
int hh = 0, tt = -1;
for (int i = 1; i <= n; i ++ )
if (!d[i])
q[ ++ tt] = i;
while (hh <= tt) {
int t = q[hh ++ ];
for (int i = h[t]; ~i; i = ne[i]) {
int j = e[i];
d[j] -- ; // h[t]的入度为0,删掉与它相关的所有出边
if (!d[j]) q[ ++ tt] = j; // 如果与 h[t] 删边完的出边入度是 0 的话,就可以将其加入队列,更新其它点了
}
}
// 若所有点都入队,即存在拓扑排序
return tt == n - 1;
}
int main() {
int T;
scanf("%d", &T);
while (T -- ) {
scanf("%d%d", &n, &m);
memset(h, -1, (n + 1) * 4); // 不要直接 sizeof h,memset 时间是线性的
memset(d, 0, (n + 1) * 4); // 下标是从 1 开始的,(a, b) 下标从 1 开始,用到 h[1]~h[n]
idx = k = 0;
while (m -- ) {
int t, a, b;
scanf("%d%d%d", &t, &a, &b);
if (!t) edges[k ++ ] = {a, b}; // 无向边
else {
add(a, b); // 有向边
d[b] ++ ; // 入度加 1
}
}
if (!topsort()) puts("NO"); // 有向边不可以拓扑排序,则不能构成DAG
else {
puts("YES");
// 输出所有有向边
for (int i = 1; i <= n; i ++ )
for (int j = h[i]; ~j; j = ne[j])
printf("%d %d\\n", i, e[j]);
// 无向边定义方向,拓扑排序前方的边方向指向后方
for (int i = 0; i < n; i ++ ) pos[q[i]] = i; // 记录拓扑排序每个点的下标
// 遍历所有无向边
for (int i = 0; i < k; i ++ ) {
int a = edges[i].a, b = edges[i].b;
if (pos[a] > pos[b]) swap(a, b); // 方向从前向后
printf("%d %d\\n", a, b);
}
}
}
return 0;
}
以上是关于[拓扑排序] aw3696. 构造有向无环图(拓扑排序+memset使用坑点+aw周赛004_3)的主要内容,如果未能解决你的问题,请参考以下文章