E. Directing Edges(拓扑排序)

E. Directing Edges(拓扑排序)

思路:拓扑排序。

考虑只由有向边组成的图。

显然若该图有环显然无解。

否则必然有解。

因为:该有向图是一个 D A G DAG 能构成一个拓扑序,假设当前我们有一条无向边从拓扑序尾连向拓扑序首,显然我们可以改变该边的方向:即让拓扑序较小的点指向拓扑序较大的点,这样就不会破坏原有的拓扑序,使得该图仍为 D A G DAG

#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;
}

猜你喜欢

转载自blog.csdn.net/weixin_45750972/article/details/107451345
今日推荐