拓扑序
拓扑序分解法
拓扑排序
事件之间的前后关系会形成一个图形结构
将图形转为序列就是拓扑排序
每次找入度为0的点,添加到队列,并将连接这个点的点的入度-1
再次找入读为0的店
//
// Created by cry on 2024/4/5.
//
#include <iostream>
#include <vector>
#include <set>
using namespace std;
#define MAX_N 2000
int in_degree_tuopupaixu[MAX_N+5]={0};
//关系
void acm_1_9_digui_tuopupaixu_test(){
vector<vector<int>> g(MAX_N+5);
int ans[MAX_N+5],cnt=0;
int n,m;
cin >> n >>m;
for(int i=0,a,b;i<m;i++) {
cin >>a >> b;
in_degree_tuopupaixu[b]+=1; //入度+=1
g[a].push_back(b); //a节点添加一个b节点
}
//使用优先队列,将点添加到优先队列
set<int> q;
for(int i=1;i<=n;i++){
if(in_degree_tuopupaixu[i]==0){
q.insert(i);//添加入度为0的点
}
}
while(q.size()>0){ //循环直到队列不为空
int now=*q.begin(); //取到堆顶元素
q.erase(q.begin()); //出队 堆顶元素
//答案就在出队的过程,就是now
ans[cnt++]=now;
for(int i=0,I=g[now].size();i<I;i++){
int t=g[now][i]; //指向的节点的编号的入度-1
in_degree_tuopupaixu[t]-=1;
if(in_degree_tuopupaixu[t]==0){
q.insert(t);
}
}
}
for(int i=0;i<cnt;i++){
if(i)cout <<" ";
cout <<ans[i];
}
}
int main(){
acm_1_9_digui_tuopupaixu_test();
return 0;
}
python的优先队列为heapq
pq=[] #初始化 heapq.heappush(pq,4) #添加 heapq.heapppo(pq) #弹出最小元素
#!/usr/bin/python3
# _*_ coding: utf-8 _*_
#
# Copyright (C) 2024 - 2024 Cry, Inc. All Rights Reserved
#
# @Time : 2024/4/5 17:51
# @Author : Cry
# @File : 拓扑排序.py
# @IDE : PyCharm
from collections import deque
# 拓扑排序
# 样例输入
# 7 6 //表示7个点,m行
# 1 2
# 1 4
# 2 3
# 4 5
# 3 6
# 5 6
# 样例输出
# 1 2 3 4 5 6 7
import heapq
def tuopu_test():
n,m=map(int,input().split())
MAX_N=2000+5
g=[[] for _ in range(MAX_N)]
ans=[0]*MAX_N
inde=[0]*MAX_N
for i in range(m):
a,b=map(int,input().split())
inde[b]+=1;
g[a].append(b)
q=[]
cnt=0
for i in range(1,n+1):
if(inde[i]==0):
heapq.heappush(q,i);
while(len(q)>0):
now=heapq.heappop(q)
ans[cnt]=now
cnt+=1
for i in range(len(g[now])):
t=g[now][i]
inde[t]-=1
if(inde[t]==0):
heapq.heappush(q,t)
for i in range(cnt):
if i:
print(" ",end="")
print(ans[i],end="")
tuopu_test()
HZOJ 636 旅行计划
//
// Created by cry on 2024/4/5.
//
#include <iostream>
#include <vector>
#include <queue>
using namespace std;
#define MAX_N 100000
void acm_1_9_digui_lvxingjihua_test(){
int n,m;
scanf("%d%d",&n,&m);
int indeg[MAX_N+5]={0};
vector<vector<int>> g(MAX_N+5);
for (int i=0,x,y;i<m;i++){
scanf("%d%d",&x,&y);
indeg[y]+=1;
g[x].push_back(y);
}
int ans[MAX_N+5]={0};
queue<int> q;
for(int i=1;i<=n;i++){
if(indeg[i]) continue;
q.push(i);
ans[i]=1;
}
//拓扑求解
while(!q.empty()){
int now=q.front();
q.pop();
for(int i=0,I=g[now].size();i<I;i++){
int t=g[now][i];
indeg[t]-=1;
if(indeg[t]==0){
q.push(t);
}
ans[t]=max(ans[now]+1,ans[t]); //找最大值
}
}
//输出ans
for(int i=1;i<=n;i++){
printf("%d\n",ans[i]);
}
}
int main(){
acm_1_9_digui_lvxingjihua_test();
return 0;
}
python
用deque的popleft和append
#!/usr/bin/python3
# _*_ coding: utf-8 _*_
#
# Copyright (C) 2024 - 2024 Cry, Inc. All Rights Reserved
#
# @Time : 2024/4/5 20:17
# @Author : Cry
# @File : 旅行计划.py
# @IDE : PyCharm
from collections import deque
def test():
MAX_N=100005
n,m=map(int,input().split())
indeg=[0]*MAX_N #各个节点入度
ans=[0]*MAX_N #结果
q=deque() #队列
g=[[] for _ in range(MAX_N)]
for i in range(m):
a,b=map(int,input().split())
indeg[b]+=1 #节点入度+1
g[a].append(b) #a节点连接b节点
for i in range(1,n+1):
if(indeg[i]):
continue
q.append(i) #如果入度为0,添加到队列
ans[i]=1;
while(q):
now=q.popleft() #取出队列元素
for i in range(len(g[now])):
t=g[now][i]
indeg[t]-=1 #将连接入度为0的点的节点入度-1
if(indeg[t]==0): #-1后入度为0就添加到队列
q.append(t)
ans[t]=max(ans[t],ans[now]+1) #找最大的
for i in range(1,n+1):
print(ans[i])
test()
归并排序O(nlogn)
一共logn层,每层归并n次 :nlogn
- 分治 :每次分两份,一直分到足够小,比如两个,足够小的进行排序
- 归并:先左边后右边,小份进行合并且排序(用指针比较较小的,放入temp完成归并)
//
// Created by cry on 2024/4/5.
//
#include <iostream>
using namespace std;
int *buff_guibing;
#define BIG_DATA_N 10000
void acm_1_6_paixu_guibing(int *arr,int l,int r){ //arr待排序数组 l和r为排序范围
if (r-l<=1) return ; //小于等于1个,不需要排序
int mid=(l+r)/2;
//先左右分治
acm_1_6_paixu_guibing(arr,l,mid);
acm_1_6_paixu_guibing(arr,mid,r);
//归并
int p1=l,p2=mid,k=0; //p1 p2为两个数组的起始位置,k为temp数组起始位置
// int *temp=(int *) malloc(sizeof(int)*(r-l)); //temp可以改进,放到外面
while(p1<mid || p2<r){
if(p2==r || p1<mid && arr[p1]<=arr[p2]){
//什么时候将第一个元素放到temp?
//1.p2为空
//2.p1不为空 且p1的值小于p2的值
// temp[k++]=arr[p1++];
buff_guibing[k++]=arr[p1++];
}
else{ //否则就是p2放到temp
// temp[k++]=arr[p2++];
buff_guibing[k++]=arr[p2++];
}
}
//将temp元素复制回arr
for(int i=l;i<r;i++){
// arr[i]=temp[i-l];
arr[i]=buff_guibing[i-l];
}
//销毁temp
// free(temp);
return;
}
void acm_1_6_paixu_guibing_test() {
// 创建一个随机整数数组
int n = 10;
int arr[n];
for (int i = 0; i < n; i++) {
arr[i] = rand() % 100;
}
// 打印原始数组
cout << "原始数组: ";
for (int i = 0; i < n; i++) {
cout << arr[i] << " ";
}
cout << endl;
//将temp放到外面,直接一次开辟足够大的空间
buff_guibing=(int *)malloc(sizeof(int)*BIG_DATA_N);
// 对数组进行快速排序
acm_1_6_paixu_guibing(arr, 0, n);
free(buff_guibing);
// 打印排序后的数组
cout << "排序后数组: ";
for (int i = 0; i < n; i++) {
cout << arr[i] << " ";
}
cout << endl;
}
归并排序转非递归
将[0,10)分成[0,5)和[5,10)
[0,5)分成[0,2)和[2,5)
[5,10)分成[5,7)和[7,10)
将以上当成要递归的图,递归为从下到上从[0,2)到[0,5)到[0,10)
342

被折叠的 条评论
为什么被折叠?



