题目
题意:
给你很多条边,这其中有无向边和有向边,你现在要将全部无向边变成有向边,但是要保证不能出现环,如果没有满足条件的情况,那么输出NO,如果满足输出YES以及每一条边。
思路:
因为有向边的已经确定了,所以就可以直接存度,然后我们开始考虑无向边,假如此时的无向边的的其中一个度为
0
0
0,那么我们就将无向边的方向指向另一个顶点,那么此时的入度还是为
0
0
0,假如此时的入度都不为
0
0
0,那么此时无论取哪个都对于判定是否有环没有影响,如果因为其他边的原因,这个无向边有度为
0
0
0的时候,那么依旧指向另外一个,所以也就是说,无向边的指向对于有无环没有任何影响。
所以最后的时候,我们只要用拓扑排序判定有向边是否有环,还有用一个数组记录此时这个点的出现的顺序,因为无向边的顶点的指向是有规定的,如果拓扑排序的时候后出现的那个点,肯定就是被指的那个点,不然起始点的度就不会为
0
0
0了。
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <queue>
#include <vector>
#include <string>
#include <cmath>
#include <set>
#include <map>
#include <deque>
#include <stack>
#include <cctype>
using namespace std;
typedef long long ll;
typedef vector<int> veci;
typedef vector<ll> vecl;
typedef pair<int, int> pii;
template <class T>
inline void read(T &ret) {
char c;
int sgn;
if (c = getchar(), c == EOF) return ;
while (c != '-' && (c < '0' || c > '9')) c = getchar();
sgn = (c == '-') ? -1:1;
ret = (c == '-') ? 0:(c - '0');
while (c = getchar(), c >= '0' && c <= '9') ret = ret * 10 + (c - '0');
ret *= sgn;
return ;
}
int xxxxxxxxx = 1;
inline void outi(int x) {if (x > 9) outi(x / 10);putchar(x % 10 + '0');}
inline void outl(ll x) {if (x > 9) outl(x / 10);putchar(x % 10 + '0');}
inline void debug(ll x) {cout << xxxxxxxxx++ << " " << x << endl;}
inline void debugs(string s) {cout << s << endl;}
const int maxn = 2e5 + 10;
int in[maxn], id[maxn];
vector<int> edge[maxn];
vector<pii > vec;
int main() {
int t; read(t); while (t--) {
vec.clear();
for (int i = 0; i <= maxn; i++) edge[i].clear();
memset(in, 0, sizeof(in));
memset(id, 0, sizeof(id));
int n, m; read(n), read(m); for (int i = 0; i < m; i++) {
int opt, u, v; read(opt), read(u), read(v);
if (opt == 1) in[v]++, edge[u].push_back(v);
else vec.push_back(make_pair(u, v));
}
queue<int> q;
for (int i = 1; i <= n; i++) if (in[i] == 0) q.push(i);
int sz = 0;
while (!q.empty()) {
int u = q.front(); q.pop();
id[u] = sz++;
for (int i = 0; i < edge[u].size(); i++) {
int v = edge[u][i];
in[v]--;
if (in[v] == 0) q.push(v);
}
}
if (sz != n) {
printf("NO\n");
continue;
} else {
printf("YES\n");
for (int i = 1; i <= n; i++) {
for (int j = 0; j < edge[i].size(); j++) {
int v = edge[i][j];
printf("%d %d\n", i, v);
}
}
for (int i = 0; i < vec.size(); i++) {
int u = vec[i].first, v = vec[i].second;
if (id[u] > id[v]) swap(u, v);
printf("%d %d\n", u, v);
}
}
}
return 0;
}