Codeforces Round #656 (Div. 3) E(拓扑排序)

题意

给你一个图,图中有无向边和有向边,要你把无向边变成有向边,问有没有一种变法,是的图没有环,如果有输出yes,并且输出这个变化方案,如果没有输出no。

题解

其实打比赛的时候就有点想法,但是没有时间了。就直接topsort,排序的时候,如果碰到无向边,就给他加一个方向就可以了,具体看代码吧。

#include <bits/stdc++.h>
#define ll long long
#define pi pair<int,int>
#define mk make_pair
#define pb push_back
using namespace std;
 
const int maxn = 2e5+10;
vector<int>G[maxn];
struct node{
    
    
	int op,u,v;
}a[maxn];
 
int in[maxn];
map<pi,int>mp,vis;
 
bool topsort(int n)
{
    
    
	queue<int>q;
	for(int i=1;i<=n;i++)if(in[i] == 0)q.push(i);
	while(q.size())
	{
    
    
		int u = q.front();
		q.pop();
		for(int i=0;i<G[u].size();i++)
		{
    
    
			int v = G[u][i];
			if(vis[mk(v,u)] == 2)continue;
			if(mp[mk(u,v)]) {
    
    
				vis[mk(u,v)] = 2;
				continue;
			}
			if((--in[v]) == 0)q.push(v);
		}
	}
	for(int i=1;i<=n;i++)if(in[i])return false;
	return true;
}
 
int main()
{
    
    
	int T;
	cin >> T;
	while(T--)
	{
    
    
		int n,m;
		scanf("%d%d",&n,&m);
		mp.clear();
		vis.clear();
		for(int i=1;i<=n;i++)in[i] = 0, G[i].clear();
		for(int i=1;i<=m;i++)
		{
    
    
			scanf("%d%d%d",&a[i].op,&a[i].u,&a[i].v);	
			if(a[i].op == 1)
			{
    
    
				in[a[i].v]++;
				G[a[i].u].pb(a[i].v);
			}
			else
			{
    
    
				mp[mk(a[i].u , a[i].v)] = 1;
				mp[mk(a[i].v , a[i].u)] = 1;
				G[a[i].u].pb(a[i].v);
				G[a[i].v].pb(a[i].u);
			}
		}
		
		bool ok = topsort(n);
		if(ok)
		{
    
    
			puts("YES");
			for(int i=1;i<=m;i++)
			{
    
    
				if(a[i].op == 1)printf("%d %d\n",a[i].u,a[i].v);
				else 
				{
    
    
					if(vis[mk(a[i].u,a[i].v)] == 2)printf("%d %d\n",a[i].u,a[i].v);
					else if(vis[mk(a[i].v,a[i].u)] == 2)printf("%d %d\n",a[i].v,a[i].u);
				}
			}
		}
		else puts("NO");
	} 
	return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_44499508/article/details/107450251