E. Directing Edges(拓扑排序)
思路:拓扑排序。
考虑只由有向边组成的图。
显然若该图有环显然无解。
否则必然有解。
因为:该有向图是一个 能构成一个拓扑序,假设当前我们有一条无向边从拓扑序尾连向拓扑序首,显然我们可以改变该边的方向:即让拓扑序较小的点指向拓扑序较大的点,这样就不会破坏原有的拓扑序,使得该图仍为 。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=2e5+5,M=2e5+5,inf=0x3f3f3f3f,mod=1e9+7;
#define mst(a) memset(a,0,sizeof a)
#define lx x<<1
#define rx x<<1|1
#define reg register
#define PII pair<int,int>
#define fi first
#define se second
#define pb push_back
int n,m,cnt,tmp[N],id[N];
int *in;
PII a[N<<1];
vector<vector<int> >e;
void topo(){
queue<int>q;
for(int i=1;i<=n;i++)
if(!in[i]) q.push(i);
while(!q.empty()){
int u=q.front();q.pop();
id[u]=++cnt;
for(auto v:e[u])
if(--in[v]==0) q.push(v);
}
}
int main(){
int t;
scanf("%d",&t);
while(t--){
cnt=0;
mst(in);
scanf("%d%d",&n,&m);
e=vector<vector<int> >(n+1);
for(int i=1,u,v,op;i<=m;i++){
scanf("%d%d%d",&op,&u,&v);
a[i]=make_pair(u,v);
if(op) e[u].pb(v),in[v]++;
}
topo();
if(cnt<n) puts("NO");
else {
puts("YES");
for(int i=1,u,v;i<=m;i++){
u=a[i].fi,v=a[i].se;
if(id[u]<id[v]) printf("%d %d\n",u,v);
else printf("%d %d\n",v,u);
}
}
}
return 0;
}