本周初始拟定任务
学会树的基础算法--最小生成树模板
洛谷模板题链接:[P3366](https://www.luogu.org/problem/P3366)
#include<iostream>
#include<string.h>
#include<algorithm>
#include<cstdio>
using namespace std;
const int maxn=2e5+10;
int findx[maxn],res=0,N,M,sum=0;
struct node{//记录每一个节点的起始和终点,以及边的权值
int x,y,value;
}my[maxn];
int check(int x){//判断两个节点是否连通,并查集思想
if(x==findx[x])return x;
else return findx[x]=check(findx[x]);
}
bool cmp(node x,node y){//将每一个边按照权重从小到大排顺序
return x.value<y.value;
}
int kruskal(){//克鲁斯卡尔算法,prim(普里姆)算法还未开始学习
for(int i=0;i<M;i++){
int a=check(my[i].x);
int b=check(my[i].y);
if(a!=b){//不连通则进行相连,连的边数加一,否则则说明当前最小权值连通之后构成了环,故不连
findx[a]=b;
res+=my[i].value;
sum++;
}
if(sum==N-1)return res;//直到连的边等于节点的个数减1退出程序,此时已构成最小生成树
}
return -1;
}
int main(){
cin>>N>>M;
for(int i=0;i<M;i++)
scanf("%d%d%d",&my[i].x,&my[i].y,&my[i].value);
for(int i=0;i<=N;i++)findx[i]=i;
sort(my,my+M,cmp);
if(kruskal()==-1)cout<<"org";
else cout<<res;
return 0;
}
学会图的基础算法--最短路基本模板,以及最短路的堆优化
洛谷模板题链接:[P4779](https://www.luogu.org/problem/P4779)
#include<iostream>
#include<cstdio>
#include<queue>
using namespace std;
const int maxn=2e9+3;
int next[200010],head[200010],val[200010],to[200010],T;
bool vis[100010];
struct node{
int x,v;
node(int xx,int vv){
x=xx;v=vv;
}
bool operator <(const node p)const{//重载运算符<,用来优先队列的初始化
return v>p.v;//按照权重最大的排在最上面
}
};
inline void addbian(int x,int y,int z){
next[++T]=head[x];//next数组表示与当前起点相同的下一条边在哪
head[x]=T;//head数组指的是当前起点是在第几次输入的
to[T]=y;//to代表起点对应的终点是哪个节点
val[T]=z;//记录第T条边的权值
}
int main(){
int N,M,S,a,b,c;
int dis[100010];
cin>>N>>M>>S;
for(int i=1;i<=N;i++)dis[i]=maxn;//先将起点到每一个节点的距离都设置为很大,以此来更新最短路径
for(int i=0;i<M;i++){
scanf("%d%d%d",&a,&b,&c);
addbian(a,b,c);
}
dis[S]=0;//将起点到自己更新为0
priority_queue<node>my;//定义优先队列,优先队列的存储结构为树形结构,重载之后大的在上,小的在下
my.push(node(S,0));
while(!my.empty()){//每一轮更新之后最上面的均是最短路径对应的终点节点,以此来更新下一个与终点节点的最短路径
int now=my.top().x;
my.pop();
if(vis[now])continue;
vis[now]=1;
for(int i=head[now];i;i=next[i]){//i代表起点相同的节点--->下一个终点,更新该中的时对应的最短路
if(dis[now]+val[i]<dis[to[i]]&&!vis[to[i]]){//判断是否满足更新
dis[to[i]]=dis[now]+val[i];
my.push(node(to[i],dis[now]+val[i]));
}
}
}
for(int i=1;i<=N;i++){
if(dis[i]==maxn)printf("2147483647 ");//这个是上一个弱化版要求输出的值,所以没改
else
printf("%d ",dis[i]);
}
return 0;
}
多元最短路模板:(没找到模板题,有一道题用到了多元最短路,主要是Floyd算法)
树网的核:[牛客竞赛](https://ac.nowcoder.com/acm/contest/1113/G)
#include<iostream>
#include<algorithm>
using namespace std;
int n,s,floyd[310][310],dis,res=1e8;
int main(){
int x,y,z;
cin>>n>>s;
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
if(i!=j)
floyd[i][j]=1e8;
}
}
for(int i=1;i<n;i++){//存邻阶矩阵
cin>>x>>y>>z;
floyd[x][y]=z;
floyd[y][x]=z;
}
for(int k=1;k<=n;k++)
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
floyd[i][j]=min(floyd[i][k]+floyd[k][j],floyd[i][j]);//根据邻接矩阵的值进行节点之间最短路径的更新
for(int i=1;i<=n;i++){
for(int j=i;j<=n;j++){
if(floyd[i][j]<=s){
dis=0;
for(int k=1;k<=n;k++){
dis=max(dis,(floyd[k][i]+floyd[k][j]-floyd[i][j])/2);
}
res=min(res,dis);
}
}
}
cout<<res;
return 0;
}
二叉排序数的实现:
代码如下:
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const ll N=3e5+10;
int T=1,n;
struct NODE{
int lc,rc,v,cnt;//cnt记录相同数字时有多少个
}node[N];
void build(int now,int val){//当前节点位置,值,从小到大排序,如果从大到小只需要将lc改成rc即可
if(!node[now].v){node[now].v=val,node[now].cnt++;return;}//如果当前节点为赋值,则为其赋值
if(node[now].v==val){node[now].cnt++;return;}//如果值相等,则使cnt计数加1就行
if(node[now].v<val){
if(!node[now].rc)node[now].rc=++T;//如果当前节点左孩子为申请,则进行申请
build(node[now].rc,val);//对左孩子进行赋值
}else {
if(!node[now].lc)node[now].lc=++T;
build(node[now].lc,val);
}
}
void print(int now){
if(!node[now].v)return ;
if(node[now].lc)print(node[now].lc);//一直遍历到最左边的孩子
for(int i=0;i<node[now].cnt;i++)cout<<node[now].v<<" ";//输出当前节点对应的值的个数
if(node[now].rc)print(node[now].rc);//然后遍历右孩子
}
int main(){
cin>>n;
for(int i=1;i<=n;i++){
cin>>x;
build(1,x);//从节点1开始插入
}
print(1);
return 0;
}