Acwing 3696-构造有向无环图 / 拓扑排序 / 指定无向边的方向,让其和有向边一起构造成一个拓扑图

Acwing 3696-构造有向无环图
开始想了半天没想明白,后来突然想到这个题目这个名称,或许是一个模板题。我不知道是不是模板题,但我当模板题记下来,因为我理解不了。

操作:

1. 读边时有向边指向的点入度增加,无向边入度都为 0, 用结构体存下所有无向边
2. 进行一次 top_sort,只要点入度为 0,就加入队列,不管这个入度为 0 的点是有向边的点还是无向边的点,且给依次出队的点标序 (pos[t] = order ++ )
3. 如果 top_sort 后出队的点的总数为总点数,则可以构造一个有向无环图,然后才进行下面的 4,5
4. 枚举所有点,输出有向边的点的所有边
5. 枚举存放无向边的结构体的所有边,对于每条无向边里的 a,b两点,pos 小的先输出,pos 大的后输出

#include <iostream>
#include <cstring>
#include <queue>
using namespace std;
const int N = 2e5 + 10, M = N;
int e[M], ne[M], h[N], idx;
int d[N], pos[N];
int n, m, T;
int u;
struct node
{
int a, b;
}edge[M]; // 存无向边
void add(int a, int b)
{
e[idx] = b, ne[idx] = h[a], h[a] = idx ++ ;
}
int top_sort()
{
queue<int>q;
for (int i = 1; i <= n; i ++ )
if (d[i] == 0) q.push(i);
int order = 0, sum = 0;
while (q.size())
{
int t = q.front();
q.pop();
sum ++ ;
pos[t] = order ++ ;
for (int i = h[t]; i != -1; i = ne[i])
{
int j = e[i];
d[j] -- ;
if (d[j] == 0) q.push(j);
}
}
return sum == n;
}
int main()
{
cin >> T;
while (T -- )
{
idx = 0, u = 0;
memset(h, -1, sizeof h);
memset(d, 0, sizeof d);
scanf("%d%d", &n, &m);
while (m -- )
{
int type, a, b;
scanf("%d%d%d", &type, &a, &b);
if (type == 1) add(a, b), d[b] ++ ;
else edge[u ++ ] = {a, b};
}
int t = top_sort();
if (t == 0) printf("NO\n");
else {
printf("YES\n");
for (int k = 1; k <= n; k ++ )
for (int i = h[k]; i != -1; i = ne[i])
printf("%d %d\n", k, e[i]);
for (int i = 0; i < u; i ++ )
{
int a = edge[i].a, b = edge[i].b;
if (pos[a] < pos[b]) printf("%d %d\n", a, b);
else printf("%d %d\n", b, a);
}
}
}
return 0;
}
posted @   妃即  阅读(13)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示