Coloring Edges(Codeforces-1217D)(有向图返祖边染色)

前言

可能以前会,但现在不会,但又会了

题目

在这里插入图片描述
在这里插入图片描述

思路

说白了就是找环后将返祖边颜色染为2
我们可以复习一下有向图DFS树边的类型,树边、返祖边、横叉边、后向边
怎么找环呢,我们并不能简单的vis,因为可能这样:
在这里插入图片描述
于是我们需要给每个点3个状态:未访问,正在访问它的子树,已访问。
当然我们可以用栈来维护此时访问的点,但也能用不同标记表示
我们1次DFS可能找不完点,要注意一下需要多次DFS,一定可以把访问到的环至少一条边找完

代码

#include<set>
#include<map>
#include<stack>
#include<ctime>
#include<cmath>
#include<queue>
#include<cstdio>
#include<vector>
#include<climits>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#define LL long long
using namespace std;
int read(){
	bool f=0;int x=0;char c=getchar();
	while(c<'0'||'9'<c){if(c=='-')f=1;c=getchar();}
	while('0'<=c&&c<='9') x=(x<<3)+(x<<1)+(c^48),c=getchar();
	return !f?x:-x;
}
#define MAXN 100000
#define INF 0x3f3f3f3f
struct Edge{
	int v,id,nxt;
}edge[2*MAXN+5];
int ecnt,head[MAXN+5];
inline void Addedge(int u,int v,int id){
	edge[++ecnt]=(Edge){v,id,head[u]},head[u]=ecnt;
	return ;
}
bool f;
int col[MAXN+5],vis[MAXN+5];
void DFS(int u){
	vis[u]=1;
	for(int i=head[u];i;i=edge[i].nxt){
		int v=edge[i].v,id=edge[i].id;
		col[id]=1;
		if(vis[v]){
			if(vis[v]==1)
				f=1,col[id]=2;
			continue;
		}
		DFS(v);
	}
	vis[u]=2;
	return ;
}
int main(){
	int n=read(),m=read();
	for(int i=1;i<=m;i++){
		int u=read(),v=read();
		Addedge(u,v,i);
	}
	for(int i=1;i<=n;i++)
		if(!vis[i])
			DFS(i);
	puts(f?"2":"1");
	for(int i=1;i<=m;i++)
		printf("%d",col[i]),putchar(i==m?'\n':' ');
	return 0;
}

后记

在网上发现了更好的做法,你跑一遍拓扑排序判环,如果没有环全输出1,否则一个环上一定存在 u > v u>v u>v 的边和 u < v u<v u<v 的边,不是环上的边可以不管(1,2颜色都可以)于是直接 u > v u>v u>v 的边颜色为1, u < v u<v u<v 的边颜色为2即可
妙啊!

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值