
题目分析:
- 这题可以用拓扑排序,我们可以这样加边,先按拓扑排序,把入度为0 的加入 队列,(这题无向边入度不加),遍历他的所有边,如果碰到一条他连出去的无向边 并且这条无向边还没有被标记过,那么直接标记一下,这样做就一定能保证无环,如果最终所有的点里面还有点没有入队过,说明这些点在环中,则说明没有可行的方案,直接输出 -1
Code:
#include <bits/stdc++.h>
using namespace std;
#define re register
#define maxn 100010
#define maxm 100010
int st[maxn],top=0,n,m_1,m_2,size=0,du[maxn],head[maxn];
struct edge {
int u,v,w,nxt;
}e[maxm+maxm<<1];
inline int read_() {
int x=0,f=1;
char c=getchar();
while(c<'0'||c>'9') {
if(c=='-') f=-1;
c=getchar();
}
while(c>='0'&&c<='9') {
x=(x<<1)+(x<<3)+c-'0';
c=getchar();
}
return x*f;
}
inline void clean_() {
memset(head,-1,sizeof(head));
memset(du,0,sizeof(du));
}
inline void add_(int u,int v,int w) {
e[++size].u=u;
e[size].v=v;
e[size].w=w;
e[size].nxt=head[u];
head[u]=size;
}
inline void topu_() {
for(re int i=1;i<=n;++i) {
if(!du[i]) st[++top]=i;
}
int t=0;
while(t<top) {
int u=st[++t];
for(re int i=head[u];~i;i=e[i].nxt) {
int v=e[i].v,w=e[i].w;
if(!w) {
--du[v];
if(!du[v]) st[++top]=v;
}
}
for(re int i=head[u];~i;i=e[i].nxt) {
int v=e[i].v,w=e[i].w;
if(w==1) e[i^1].w=2;
}
}
for(re int i=1;i<=size;++i) {
if(e[i].w==1) {
printf("%d %d\n",e[i].u,e[i].v);
}
}
}
void readda_() {
n=read_();m_1=read_();m_2=read_();
clean_();
int x,y;
for(re int i=1;i<=m_1;++i) {
x=read_();y=read_();
add_(x,y,0);
++du[y];
}
if( ! (size%2) ) {
++size;
}
for(re int i=1;i<=m_2;++i) {
x=read_();y=read_();
add_(x,y,1);add_(y,x,1);
}
topu_();
}
int main() {
readda_();
return 0;
}