题目链接
https://www.luogu.org/problemnew/show/P2017
题目大意
给定一张 点, 条有向边, 条无向边,现要给每条无向边一个方向,使这张图变成一张有向无环图
解题思路
:将一张有向无环图的元素进行排序使其满足拓扑次序
注:紫色为已出队,红色为当前准备拓展点,蓝色为被拓展点,黄色为还在队内的已被拓展点
具体实现如下:
首先读入
条有向边,然后找到入度为0的点(可能有多个),将它们入队(入度为0的点的入队顺序不影响结果所以任选一个作为队首都行,所以标红),如下图
然后每次以队首进行拓展,将其邻接点的入度统统减少1,若有点的入度变成0了,则将其入队
然后让队首出队,继续用下一个队首进行拓展
继续扩展
再拓展,此时4的出度为0,跳过
然后继续拓展
继续
继续拓展,发现没有入度了,结束
此时队列为空,结束
想知道这些图我是怎么画的吗?点这里:https://www.processon.com/i/5afc01e3e4b096c6eeb3834b
代码
#include<queue>
#include<cstdio>
#include<cstring>
#define N 100001
using namespace std;
struct node{int next,to;}e[N<<2];
int rd[N],l[N<<1],n,m1,m2,x,y,t[N],len,tot;
queue<int>q;
void add(int u,int v)
{
e[tot]=(node){l[u],v};l[u]=tot++;
return;
}
int main()
{
freopen("dizzy.in","r",stdin);
freopen("dizzy.out","w",stdout);
memset(l,-1,sizeof(l));
scanf("%d%d%d",&n,&m1,&m2);
for(int i=1;i<=m1;i++) scanf("%d%d",&x,&y),add(x,y),rd[y]++;
for(int i=1;i<=n;i++) if(!rd[i]) t[i]=++len,q.push(i);
while(q.size())
{
x=q.front();q.pop();
for(int j=l[x];~j;j=e[j].next)
if(!(--rd[e[j].to])) t[e[j].to]=++len,q.push(e[j].to);//拓扑排序
}
for(int i=1;i<=m2;i++)
{
scanf("%d%d",&x,&y);
if(t[x]<t[y]) printf("%d %d\n",x,y);else printf("%d %d\n",y,x);//谁更晚入队就连谁
}
}