目录
拓扑排序想必不用再多介绍了,下面来看看拓扑排序的一个板子(遍历某一个点的所有边),并做两道拓扑排序相关的例题。
直接看代码。
- #include
- #include
// 拓扑排序经常需要用到队列 - #include
- using namespace std;
-
- const int N=10010;
- int n,m; //顶点数,边数
- int e[N],h[N],ne[N],idx; //某边终点、以某点为起点的第一条边、以某点为起点的下一条边、第idx条边
- int degree[N]; //存储对应点的入度
-
- void Add(int a,int b){
- e[idx]=b,ne[idx]=h[a],h[a]=idx++;
- }
-
- void topsort(){
- queue<int> q;
- for(int i=1;i<=n;++i)
- if(!degree[i])
- q.push(i);
-
- while(!q.empty()){
- int t=q.front();
- q.pop();
- cout<
" "; -
- for(int i=h[t];~i;i=ne[i]){
- int j=e[i];
- if(--degree[j]==0)
- q.push(j);
- }
- }
- cout<
- }
-
- int main(){
-
- cin>>n>>m;
-
- memset(h,-1,sizeof h); //所以~i能结束
-
- for(int i=0;i
- int a,b;
- cin>>a>>b;
- Add(a,b); //把当前的边存起来
- degree[b]++;
- }
-
- topsort();
-
- return 0;
-
- }
三、题目:拓扑顺序
1、上链接
2、基本思路
对拓扑排序的板子进行相应的修改即可。
3、代码
(1)C++(AC)
- #include
- #include
// 拓扑排序经常需要用到队列 - #include
- using namespace std;
-
- const int N=10010;
- const int K=110;
- int n,m,k; //顶点数,边数
- int e[N],h[N],ne[N],idx; //某边终点、以某点为起点的第一条边、以某点为起点的下一条边、第idx条边
- int degree[N]; //存储对应点的入度
- int ask[N],flg[K],d[N];
-
- void Add(int a,int b){
- e[idx]=b,ne[idx]=h[a],h[a]=idx++;
- }
-
- int topsort(){
- for(int i=1;i<=n;++i){
- if(d[ask[i]])
- return 0;
-
- for(int j=h[ask[i]];~j;j=ne[j]){
- d[e[j]]--;
- }
- }
- return 1;
- }
-
- int main(){
-
- cin>>n>>m;
-
- memset(h,-1,sizeof h);
-
- for(int i=0;i
- int a,b;
- cin>>a>>b;
- Add(a,b); //把当前的边存起来
- degree[b]++;
- }
-
- cin>>k;
-
- for(int i=0;i
- for(int j=1;j<=n;j++){
- cin>>ask[j];
- d[ask[j]]=degree[ask[j]];
- //或这样写,都是一样的
- // d[j] = degree[j]
- }
- if(topsort())
- flg[i]=1;
- else
- flg[i]=0;
- }
-
- int i=0;
- for(i=0;i
- if(!flg[i]){
- cout<
- break;
- }
- }
-
- i++;
- for(;i
- if(!flg[i])
- cout<<" "<
- }
- cout<
-
- return 0;
- }
(2)python(AC)
- N=10010
-
- e=[0]*N
- ne=[0]*N
- h=[-1]*N
- idx=0
-
- degree=[0]*N
- d=[0]*N
- ask=[0]*N
- flg=[0]*110
-
- def Add(a,b):
- global idx
- e[idx]=b
- ne[idx]=h[a]
- h[a]=idx
- idx=idx+1
-
- def topsort():
- for i in range(1,n+1):
- if d[ask[i]]!=0:
- return 0
- j=h[ask[i]]
- while ~j:
- d[e[j]]-=1
- j=ne[j]
- return 1
-
-
- n,m=map(int,input().split())
-
- for i in range(m):
- a,b=map(int,input().split())
- Add(a,b)
- degree[b]+=1
-
- k=int(input())
-
- for i in range(k):
- lines=list(map(int,input().split()))
- for j in range(1,n+1):
- ask[j]=lines[j-1]
- d[ask[j]]=degree[ask[j]]
- if topsort():
- flg[i]=1
- else:
- flg[i]=0
- ## print(flg[i],end="@")
- ## print("")
-
-
- c=0
- for i in range(k):
- if c==0 and flg[i]==0:
- print(i,end="")
- c=1
- elif flg[i]==0:
- print(" {}".format(i),end="")
- print("")
-
-
四、题目:可达性统计
1、上链接
2、基本思路
对拓扑排序的板子进行相应的修改即可。
3、代码
(1)C++(AC)
- #include
- #include
- #include
- #include
- using namespace std;
-
- const int N=30010;
- int n,m;
- int e[N],ne[N],h[N],idx;
- int degree[N];
- int seq[N];
-
- bitset
f[N]; -
- void Add(int a,int b){
- e[idx]=b,ne[idx]=h[a],h[a]=idx++;
- }
-
- void topsort(){
- queue<int> q;
- for(int i=1;i<=n;++i)
- if(degree[i]==0)
- q.push(i);
-
- int k=0;
- while(!q.empty()){
- int t=q.front();
- q.pop();
-
- seq[k++]=t;
- for(int i=h[t];~i;i=ne[i]){
- int j=e[i];
- if(--degree[j]==0)
- q.push(j);
- }
- }
- }
-
- int main(){
- cin>>n>>m;
- memset(h,-1,sizeof h);
- for(int i=0;i
- int a,b;
- cin>>a>>b;
- Add(a,b);
- degree[b]++;
- }
-
- topsort();
-
- for(int i=n-1;i>=0;i--){
- int j=seq[i];
- f[j][j]=1;
- for(int p=h[j];~p;p=ne[p]){
- f[j]|=f[e[p]];
- }
- }
-
- for(int i=1;i<=n;++i){
- cout<
count()< - }
-
- return 0;
- }
bitset用来处理二进制位非常方便。头文件是 #include,bitset可能在PAT、蓝桥OJ中不常用,但是在LeetCode OJ中经常用到~而且知道 bitset 能简化一些操作,可能一些复杂的问题能够直接用 bitset 就很轻易的解决了。
bitset的用法随便百度一下就能找到一大堆,这里就不啰嗦了。
解释一下为什么“ f[j] |= f[e[p]] ”,如下图。(所以序列的遍历方向从后往前)
(2)python
我也想写一个python代码,在python中,bitset也确实可以写成一个类来实现,但是这个“类bitset”并不能起到优化空间的作用,该到题的内存会爆。而直接开一个二维列表来处理每个点的可达点数,内存无疑也会爆掉,故python代码我没能写出来。
稍微算一下题目的空间:
N和M的最大数值为 30000,即数组最大初始化有 30000 个int。
开 N^2 大小的空间,就有 9*10^8 个int,我们知道 10^6 个int约等于 4M,则 9*10^8 个int会有 3600M,题目空间限制为 256M。非常遗憾,内存爆了。
稍微解释一下 “10^6 个int约等于 4M”:
4M = 1024*4kb = 1024*1024*4byte = 10^6 个int
以上,拓扑排序
祝好
-
相关阅读:
为什么选择虚拟展会展览?了解虚拟展会展览的应用领域
25、四大函数式接口(消费型接口(Consumer)和供给型接口(Supplier))
【毕业设计】大数据用户画像分析系统 - 数据分析
企业电子文档管理系统哪个好?怎么选?
谈谈系统性能调优中都需要考虑哪些因素
随着Python越来越火,前景如何?
C语言:指针的基础详解
sql update 不更新
JUC——AQS原理分析
快速排序及优化
-
原文地址:https://blog.csdn.net/m0_52711790/article/details/127885290