混合图 (h[u]误写成h[q[u]]……)

探讨了在给定N个点、M1条有向边和M2条无向边的混合图中,如何通过定向无向边来构建一个无环的图,确保图的连通性和无环性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

                                     混合图

                   (dizzy.c/cpp/pas)

【问题描述】

    有一张N个点,M1条有向边,M2条无向边组成的混合图。询问一个给所有无向边定向的方案。使得最终的图中没有环。保证一定有解。

【输入格式】

    第一行,三个数字N,M1,M2。

    接下来M1+M2行,每行两数字Ai,Bi。表示一条边。

    前M1条是有向边。方向是Ai到Bi。

【输出格式】

    输出M2行,按输出顺序输出为无向边确定的方向。Ai Bi或Bi Ai。

    有多解时输出任意解。

【样例输入】

4 2 3

1 2

4 3

1 3

4 2

3 2

【样例输出】

1 3

2 4

2 3

【数据规模】

    1<=N<=100 000

    1<=M1,M2<=100000

 


拓扑排序即使有重边也成立!

请务必注意哈希表h[u]别多套一个q[u]……



#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<iostream>
#include<functional>
#include<algorithm>
using namespace std;
#define MAXN (100000+10)
#define MAXM (100000+10)
int n,m1,m2,indegree[MAXN]={0},head[MAXN],next[MAXM]={0},edge[MAXM]={0},tot=0;
void addedge(int u,int v)
{
	edge[++tot]=v;
	next[tot]=head[u];
	head[u]=tot;
}
int q[MAXN*2];
bool b[MAXN]={0};
void topsort()
{
	int head_=1,tail=0;
	for (int i=1;i<=n;i++)
		if (indegree[i]==0) 
		{
			q[++tail]=i;b[i]=1;
		}
	while (head_<=tail)
	{
		int now=q[head_];
		int p=head[now];
		while (p)
		{
			int v=edge[p];
			indegree[v]--;
			if (indegree[v]==0)
			{
				q[++tail]=v;b[v]=1;
			}									
			p=next[p];
		}	
		head_++;
	}				
}
int h[MAXN];
int main()
{
	freopen("dizzy.in","r",stdin);
	freopen("dizzy.out","w",stdout);
	scanf("%d%d%d",&n,&m1,&m2);
	memset(head,0,sizeof(head));
	for (int i=1;i<=m1;i++)
	{
		int u,v;
		scanf("%d%d",&u,&v);
		addedge(u,v);
		indegree[v]++;
	}
	topsort();
	for (int i=1;i<=n;i++) 
	{
		h[q[i]]=i;
	//	cout<<q[i]<<' ';
	}
/*	
	for (int i=1;i<=n;i++) cout<<q[i]<<' ';
	cout<<endl;
	for (int i=1;i<=n;i++) cout<<h[i]<<' ';
	cout<<endl;
*/	
	for (int i=1;i<=m2;i++)
	{
		int u,v;
		scanf("%d%d",&u,&v);
		if (h[u]<h[v]) printf("%d %d\n",u,v);
		else printf("%d %d\n",v,u);
	}
//	while (1);
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值