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

文章目录

  • 前言
  • 题目
  • 思路
  • 代码
  • 后记

前言

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

题目

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

思路

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

代码

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#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 uu<v 的边,不是环上的边可以不管(1,2颜色都可以)于是直接 u > v u>v u>v 的边颜色为1, u < v uu<v 的边颜色为2即可
妙啊!

你可能感兴趣的:(树形结构,CodeForces,拓扑排序)