拓扑排序入门详解&&Educational Codeforces Round 72 (Rated for Div. 2)-----D
https://codeforces.com/contest/1217
D:给定一个有向图,给图染色,使图中的环不只由一种颜色构成,输出每一条边的颜色
不成环的边全部用1染色
ps:最后输出需要注意,一个环上的序号必然是非全递增的,若有环且有一条边u->v,u的序号<v则输出1否则输出2(反过来也可以)
可以用dfs染色或者用拓扑排序做
顺便复习一下拓扑排序:
拓扑排序是将有向无环图的所有顶点排成一个线性序列,使得图中任意两个顶点u,v若存在u->v,那么序列中u一定在v前面。
了解一个概念: DAG-->有向无环图,一个有向图的任意顶点都无法通过一些有向边回到自身,称之为DAG
算法过程:
(1)定义一个队列,把所有入度为0的结点加入队列(图有n个点)
(2)取队首节点,输出,删除所有从他出发的边,并令这些边的入度-1,若某个顶点的入度减为0,则将其加入队列
(3)反复进行(2)操作,直到队列为空;
注意:若队列为空时入过队的节点数目恰好为n,说明拓扑排序成功,图为DAG,否则图中有环
这位博主写的挺好的 https://blog.csdn.net/qq_41713256/article/details/80805338
#include<bits/stdc++.h> using namespace std; inline int read(){ ,w=;; while(!isdigit(ch)){w|=ch=='-';ch=getchar();} )+(X<<)+(ch^),ch=getchar(); return w?-X:X; } /*-------------------------------------------------------------------*/ typedef long long ll; ; int du[maxn]; ll cnt; int n,m; int s; vector<int>G[maxn]; pair<int,int>ans[maxn]; queue<int>q; int main() { ios_base::sync_with_stdio(); cin.tie(); cout.tie(); //一个环上的序号必然是非全递增的 cin>>n>>m; ;i<=m;i++){ int u,v; cin>>u>>v; G[u].push_back(v); ans[i].first=u;ans[i].second=v; //入度 du[v]++; } ;i<=n;i++) ) q.push(i); while(!q.empty()){ int now=q.front();q.pop(); int len=G[now].size(); ;i<len;i++){ du[G[now][i]]--;//该点入度-1 )q.push(G[now][i]); } } ; ;i<=n;i++) ){ flag=;//标记是否还存在入度不为0的点 break; } //一个环上的序号必然是非全递增的 if(flag){//说明有环 cout<<<<endl; //for(int i=1;i<=m;i++)cout<<1<<" "; ;i<=m;i++){ if(ans[i].first>ans[i].second) cout<<<<" "; <<" "; } } else{ //无环直接输出1 cout<<<<endl; ;i<=m;i++) cout<<<<" "; } ; }
DFS版:
dfs过程中有3个状态1,-1,0,1表示当前搜索路径,-1表示已搜索过且无环路径,0表示还未搜索,可以用前向星存边或者vector存边过
其他需要注意的代码有注释
ps:讲个大家不容易理解的地方,这个DFS的点是不是可以从任意起点搜索?答案:是的,这个对拓扑序列没有影响,可通过代码自由验证。
在有向图DFS过程中(不判环的情况下),我们用栈去存储他的拓扑序列,当一个点没有后驱节点时,这个节点入栈,记住栈的性质(后进先出),然后回溯,这样,越是后面的节点就会被压进栈底
比如说有向边u->v,u是v的前驱,若存在u->v>t,t在拓扑序列中一定在u的后面(拓扑排序的性质),我们从v开始搜索,到t终止(无后驱节点),回溯,入栈,v入栈,回溯。
最后我们搜索u,发现u的后驱节点已标记,所以入栈,退出完成拓扑排序
所以,以DFS回溯+栈的形式就可以很好地完成一次拓扑排序
前向星版本:
#include<bits/stdc++.h> using namespace std; inline int read(){ ,w=;; while(!isdigit(ch)){w|=ch=='-';ch=getchar();} )+(X<<)+(ch^),ch=getchar(); return w?-X:X; } /*-------------------------------------------------------------------*/ typedef long long ll; ; struct node{ int to,next; }star[]; ll cnt; int n,m; int vis[maxn],head[maxn]; void add(int u,int v){ star[cnt].to=v; star[cnt].next=head[u]; head[u]=cnt++; } bool dfs(int idx){ vis[idx]=; ;i=star[i].next){ int v=star[i].to; )return false; //若搜索过程中发现回到本次搜索过的点,说明有环,退出 &&!dfs(v))return false; } vis[idx]=-;//目前路径上不存在环,所以标记为-1 return true; } pair<int,int >p[maxn]; int main() { ios_base::sync_with_stdio(); cin.tie(); cout.tie(); //一个环上的序号必然是非全递增的 memset(head,-,sizeof(head)); cin>>n>>m; ;i<=m;i++){ int u,v; cin>>u>>v; add(u,v); p[i].first=u,p[i].second=v; } ; ;i<=n;++i){ if(!vis[i]){ if(!dfs(i)){ flag=; break; } } } if(flag){ cout<<<<endl; ;i<=m;i++){ <<" "; <<" "; } } else{ cout<<<<endl; ;i<=m;i++){ cout<<<<" "; } } ; }
vector版本:
#include<bits/stdc++.h> using namespace std; inline int read(){ ,w=;; while(!isdigit(ch)){w|=ch=='-';ch=getchar();} )+(X<<)+(ch^),ch=getchar(); return w?-X:X; } /*-------------------------------------------------------------------*/ typedef long long ll; ; struct node{ int to,next; }star[]; vector<int>edge[maxn]; ll cnt; int n,m; int vis[maxn],head[maxn]; bool dfs(int idx){ int len=edge[idx].size(); vis[idx]=; ;i<len;++i){ ); ; } vis[idx]=-; ; } pair<int,int >p[maxn]; int main() { ios_base::sync_with_stdio(); cin.tie(); cout.tie(); //一个环上的序号必然是非全递增的 memset(head,-,sizeof(head)); cin>>n>>m; ;i<=m;i++){ int u,v; cin>>u>>v; p[i].first=u,p[i].second=v; edge[u].push_back(v); } ; ;i<=n;++i){ if(!vis[i]){ if(!dfs(i)){ flag=; break; } } } if(flag){ cout<<<<endl; ;i<=m;i++){ <<" "; <<" "; } } else{ cout<<<<endl; ;i<=m;i++){ cout<<<<" "; } } ; }
对拓扑排序讲得还不错的博客:深入理解拓扑排序(Topological sort) - 简书 https://www.jianshu.com/p/3347f54a3187拓扑排序dfs版+判环_Python_姬小野的博客-CSDN博客 https://blog.csdn.net/wjh2622075127/article/details/82712940
拓扑排序入门详解&&Educational Codeforces Round 72 (Rated for Div. 2)-----D的更多相关文章
- Educational Codeforces Round 72 (Rated for Div. 2)-D. Coloring Edges-拓扑排序
Educational Codeforces Round 72 (Rated for Div. 2)-D. Coloring Edges-拓扑排序 [Problem Description] 给你 ...
- Educational Codeforces Round 72 (Rated for Div. 2)
https://www.cnblogs.com/31415926535x/p/11601964.html 这场只做了前四道,,感觉学到的东西也很多,,最后两道数据结构的题没有补... A. Creat ...
- Educational Codeforces Round 72 (Rated for Div. 2) Solution
传送门 A. Creating a Character 设读入的数据分别为 $a,b,c$ 对于一种合法的分配,设分了 $x$ 给 $a$ 那么有 $a+x>b+(c-x)$,整理得到 $x&g ...
- Educational Codeforces Round 72 (Rated for Div. 2) C题
C. The Number Of Good Substrings Problem Description: You are given a binary string s (recall that a ...
- Educational Codeforces Round 72 (Rated for Div. 2) B题
Problem Description: You are fighting with Zmei Gorynich — a ferocious monster from Slavic myths, a ...
- Educational Codeforces Round 72 (Rated for Div. 2) A题
Problem Description: You play your favourite game yet another time. You chose the character you didn ...
- Coloring Edges(有向图环染色)-- Educational Codeforces Round 72 (Rated for Div. 2)
题意:https://codeforc.es/contest/1217/problem/D 给你一个有向图,要求一个循环里不能有相同颜色的边,问你最小要几种颜色染色,怎么染色? 思路: 如果没有环,那 ...
- Educational Codeforces Round 72 (Rated for Div. 2)E(线段树,思维)
#define HAVE_STRUCT_TIMESPEC#include<bits/stdc++.h>using namespace std;#define BUF_SIZE 100000 ...
- Educational Codeforces Round 72 (Rated for Div. 2)C(暴力)
#define HAVE_STRUCT_TIMESPEC#include<bits/stdc++.h>using namespace std;char s[200007];int a[20 ...
随机推荐
- git提交更改都是一个作者
为什么提交到github的commit都是一个作者 参考链接 重要知识点讲解 问题如下所示 git是分布式去中心化的管理系统 ssh秘钥对生成.并把id_rsa.pub加入github.com中(这个 ...
- Spring框架——继承 - 依赖 - 命名空间
Spring 继承 子 bean 可以继承⽗ bean 的属性值. <bean id="user" class="com.sunjian.entity.User&q ...
- ORM单表查询,跨表查询,分组查询
ORM单表查询,跨表查询,分组查询 单表查询之下划线 models.Tb1.objects.filter(id__lt=10, id__gt=1) # 获取id大于1 且 小于10的值models ...
- 微信开发+百度AI学习:微信网页开发环境搭建
参考微信官方文档:https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421141115 两步即可获取微信网页开发能力 STEP1: ...
- 单调栈-Maximum Width Ramp
2020-01-23 19:39:26 问题描述: 问题求解: public int maxWidthRamp(int[] A) { Stack<Integer> stack = new ...
- PAT-B 1003. 我要通过!(20) Java版
"答案正确"是自动判题系统给出的最令人欢喜的回复.本题属于PAT的"答案正确"大派送 -- 只要读入的字符串满足下列条件,系统就输出"答案正确&quo ...
- pat 1044.火星数字 Java版
个人网站:https://www.lingluan.xyz 火星人是以13进制计数的: 地球人的0被火星人称为tret. 地球人数字1到12的火星文分别为:jan, feb, mar, apr, ma ...
- PySpark初级教程——第一步大数据分析(附代码实现)
概述 数据正以前所未有的速度与日俱增 如何存储.处理和使用这些数据来进行机器学习?spark正可以应对这些问题 了解Spark是什么,它是如何工作的,以及涉及的不同组件是什么 简介 我们正在以前所未有 ...
- PHP7内核(一):发展史
PHP1 1994年,一位名叫Rasmus lerdorf的兄台为了在网上展示自己的履历和网页流量的统计,用Perl开发了一套脚本,后来因与日俱增的需求无法得到满足,lerdorf便使用c语言进行了重 ...
- 开发一个健壮的npm包
项目地址:loan-calculate-utils npm包的发布.更新查看上一篇文章 开发一个基础的npm包 目前我们的目录是这个样子: . ├── source 源代码目录 │ └── ind ...