[codeforces 1385E] Directing Edges 变形的拓扑排序

Codeforces Round #656 (Div. 3)   参与排名人数11542   早睡早起身体好

[codeforces 1385E]   Directing Edges   变形的拓扑排序

总目录详见https://blog.csdn.net/mrcrack/article/details/103564004

在线测评地址https://codeforces.com/contest/1385/problem/E

ProblemLangVerdictTimeMemory
E - Directing Edges GNU C++17Accepted217 ms13300 KB

题目大意:给一幅图,里面有有向边,有无向边,要求将所有无向边变成有向边,问能得到无环图吗,若不能,输出NO.若能,输出YES,以及所有的边(有向边).

看懂此文,需要拓扑排序基础。

样例模拟如下:

5 5
0 2 1
1 1 5
1 5 4
0 5 2
1 3 5

YES
1 5
1 2
2 5
3 5
5 4

AC代码如下:

#include <stdio.h>
#define maxn 200010
struct node{
	int to,next,w;
}e[maxn<<1];
int head[maxn],q[maxn],vis[maxn],rd[maxn],tot,n,m,l[maxn],r[maxn],cnt;//rd[]入度,l[]有向边的左节点,r[]有向边的右节点
void add_edge(int u,int v,int w){//邻接表
	tot++,e[tot].to=v,e[tot].w=w,e[tot].next=head[u],head[u]=tot;
}
void init(){
	int cmd,u,v,i;
	scanf("%d%d",&n,&m);
	tot=cnt=0;//此处初始化很关键
	for(i=1;i<=n;i++)head[i]=vis[i]=rd[i]=0;//初始化
	for(i=1;i<=m;i++){
		scanf("%d%d%d",&cmd,&u,&v);
		if(!cmd)add_edge(u,v,1),add_edge(v,u,1);//无向边
		else add_edge(u,v,0),rd[v]++;//有向边
	}
}
void solve(){
	int h,t,u,v,w,b,i;
	h=t=1;
	for(i=1;i<=n;i++)
		if(!rd[i])q[t]=i,t++;//记录入度为0的点
	while(h<t){
		u=q[h],vis[u]=1;
		for(b=head[u];b;b=e[b].next){
			v=e[b].to,w=e[b].w;
			if(vis[v])continue;//针对无向边的处理
			if(w)cnt++,l[cnt]=u,r[cnt]=v;
			else if(!w){
				cnt++,l[cnt]=u,r[cnt]=v,rd[v]--;
				if(!rd[v])q[t]=v,t++;
			}
		}
		h++;
	}
	if(cnt!=m)printf("NO\n");
	else{//cnt==m,通过拓扑排序,可以删除所有边。
		printf("YES\n");
		for(i=1;i<=cnt;i++)printf("%d %d\n",l[i],r[i]);
	}
}
int main(){
	int t;
	scanf("%d",&t);
	while(t--){
		init();
		solve();
	}
	return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值