NOIP 模板 跪求大佬们指正错误
来源:互联网 发布:sql存储过程详细教学 编辑:程序博客网 时间:2024/05/22 05:33
- 图论
- 最小生成树
- kruskal
- prim
- 最短路
- 单源spfa
- 单源Dijkstra
- 并查集
- 倍增lca
- 最小生成树
====================================================
图论
最小生成树
https://www.luogu.org/problem/show?pid=3366#sub
kruskal
路径压缩#include<iostream>#include<cstdio>#include<algorithm>using namespace std;const int N=5000+500,M=200000+500;struct edge{ int s,t,v;}e[M];int fa[N],cnt,n,m;long long ans;bool cmp(edge a,edge b){ return a.v<b.v;}int find(int x){ if(x==fa[x]) return x; else return fa[x]=find(fa[x]);}void init(){ for(int i=0;i<=n;i++) fa[i]=i;}int main(){ scanf("%d%d",&n,&m); init(); for(int i=1;i<=m;i++){ scanf("%d%d%d",&e[i].s,&e[i].t,&e[i].v); } sort(e+1,e+m+1,cmp); for(int i=1;i<=m;i++){ int x=find(e[i].s),y=find(e[i].t); if(x==y) continue; fa[x]=y; cnt++; ans+=e[i].v; if(cnt==n-1) break; } if(cnt!=n-1) printf("orz"); else printf("%lld",ans); return 0;}
按秩合并 find函数和merge部分略有不同 保存了树结构
感谢大彤大佬的友情checkint find(int x){ if(x==fa[x]) return x; else return find(fa[x]);}for(int i=1;i<=m;i++){ int x=find(e[i].s),y=find(e[i].t); if(x==y) continue; if(rank[x]==rank[y]) rank[y]++; if(rank[x]>rank[y]) swap(x,y); fa[x]=y; cnt++; ans+=e[i].v; if(cnt==n-1) break;}
prim
裸的邻接矩阵,记得初始化mp数组maxx
#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>using namespace std;const int N=5000+20;int mp[N][N],d[N];int ans,n,m,a,b,c;bool used[N];void prim(int x){ memset(d,0x3f,sizeof(d)); d[x]=0; while(1){ int v=-1; for(int i=1;i<=n;i++){ if(!used[i]&&(v==-1||d[i]<d[v])) v=i; } if(v==-1) return ; used[v]=1; ans+=d[v]; for(int i=1;i<=n;i++){ if(d[i]>mp[v][i]){ d[i]=mp[v][i]; } } } return ;}int main(){ memset(mp,0x7f,sizeof(mp)); scanf("%d%d",&n,&m); for(int i=1;i<=m;i++){ scanf("%d%d%d",&a,&b,&c); mp[a][b]=min(c,mp[a][b]); mp[b][a]=min(c,mp[b][a]); } prim(1); printf("%d",ans); return 0;}
堆优化 建双向边记得开两倍数组
#include<iostream>#include<cstdio>#include<queue>#include<cstring>using namespace std;const int N=5000+500,M=200000+500;int cnt,n,m,a,b,c,tot;int first[N],next[M<<1];long long ans;bool used[N];struct node{ int t,v;}e[M<<1];priority_queue<node> Q;bool operator <(node a,node b){ return a.v>b.v;}void build(int f,int t,int v){ e[++tot]=(node){t,v}; next[tot]=first[f]; first[f]=tot; return ;}void prim(int x){ used[x]=1; for(int i=first[x];i!=-1;i=next[i]){ Q.push(e[i]); } while(!Q.empty()){ node u=Q.top(); Q.pop(); if(used[u.t]) continue; used[u.t]=1; ans+=u.v; cnt++; if(cnt==n-1) return ; for(int i=first[u.t];i!=-1;i=next[i]){ if(used[e[i].t]) continue; Q.push(e[i]); } } return ;}void init(){ memset(first,-1,sizeof(first));}int main(){ init(); scanf("%d%d",&n,&m); for(int i=1;i<=m;i++){ scanf("%d%d%d",&a,&b,&c); build(a,b,c);build(b,a,c); } prim(1); if(cnt==n-1) printf("%lld",ans); else printf("orz"); return 0;}
最短路
单源模板 https://www.luogu.org/problem/show?pid=3371
单源spfa
朴素算法,可以在一定情况下将stl中的队列改为栈or手打队列#include<iostream>#include<cstdio>#include<cstring>#include<queue>using namespace std;const int N=10000+50,M=500000+50;int n,m,a,b,c,tot,s;int first[N],next[M],dis[N];bool inq[N];queue<int> Q;struct edge{ int t,v;}e[M];void build(int ff,int tt,int vv){ e[++tot]=(edge){tt,vv}; next[tot]=first[ff]; first[ff]=tot; return ;}void spfa(int x){ for(int i=1;i<=n;i++) dis[i]=2147483647; dis[x]=0; Q.push(x); inq[x]=1; while(!Q.empty()){ int u=Q.front(); Q.pop(); inq[u]=0; for(int i=first[u];i!=-1;i=next[i]){ int v=e[i].t; if(dis[v]>dis[u]+e[i].v){ dis[v]=dis[u]+e[i].v; if(!inq[v]){ Q.push(v); inq[v]=1; } } } } return ;}int main(){ memset(first,-1,sizeof(first)); scanf("%d%d%d",&n,&m,&s); for(int i=1;i<=m;i++){ scanf("%d%d%d",&a,&b,&c); build(a,b,c); } spfa(s); for(int i=1;i<=n;i++) printf("%d ",dis[i]); return 0;}
玄学优化之双端队列(SLF优化) 应该是能优化时间复杂度,但是stl中的双端队列实现比较慢,慎重使用#include<iostream>#include<cstdio>#include<cstring>#include<deque>using namespace std;const int N=10000+50,M=500000+50;int n,m,a,b,c,tot,s;int first[N],next[M],dis[N];bool inq[N];deque<int> Q;struct edge{ int t,v;}e[M];void build(int ff,int tt,int vv){ e[++tot]=(edge){tt,vv}; next[tot]=first[ff]; first[ff]=tot; return ;}void spfa(int x){ for(int i=1;i<=n;i++) dis[i]=2147483647; dis[x]=0; Q.push_back(x); inq[x]=1; while(!Q.empty()){ int u=Q.front(); Q.pop_front(); inq[u]=0; for(int i=first[u];i!=-1;i=next[i]){ int v=e[i].t; if(dis[v]>dis[u]+e[i].v){ dis[v]=dis[u]+e[i].v; if(!inq[v]){ if(Q.empty()||dis[Q.front()]<dis[v]) Q.push_back(v); else Q.push_front(v); inq[v]=1; } } } } return ;}int main(){ memset(first,-1,sizeof(first)); scanf("%d%d%d",&n,&m,&s); for(int i=1;i<=m;i++){ scanf("%d%d%d",&a,&b,&c); build(a,b,c); } spfa(s); for(int i=1;i<=n;i++) printf("%d ",dis[i]); return 0;}
单源Dijkstra
如果要求s-t的最短路,在done[t]=1时即可直接返回
堆优化#include<iostream>#include<cstdio>#include<cstring>#include<queue>using namespace std;const int N=10000+50,M=500000+50;int n,m,a,b,c,tot,s;int first[N],next[M],dis[N];bool done[N];struct edge{ int t,v;}e[M];struct node{ int id,dis;};priority_queue<node> Q;bool operator < (node a,node b){ return a.dis>b.dis;}void build(int ff,int tt,int vv){ e[++tot]=(edge){tt,vv}; next[tot]=first[ff]; first[ff]=tot; return ;}void dij(int x){ for(int i=1;i<=n;i++) dis[i]=2147483647; Q.push((node){x,0}); dis[x]=0; while(!Q.empty()){ node u=Q.top(); Q.pop(); if(done[u.id]) continue; done[u.id]=1; for(int i=first[u.id];i!=-1;i=next[i]){ int v=e[i].t; if(dis[v]>dis[u.id]+e[i].v){ dis[v]=dis[u.id]+e[i].v; Q.push((node){v,dis[v]}); } } } return ;}int main(){ memset(first,-1,sizeof(first)); scanf("%d%d%d",&n,&m,&s); for(int i=1;i<=m;i++){ scanf("%d%d%d",&a,&b,&c); build(a,b,c); } dij(s); for(int i=1;i<=n;i++) printf("%d ",dis[i]); return 0;}
并查集
https://www.luogu.org/problem/show?pid=3367#sub
#include<iostream>#include<cstdio>using namespace std;int fa[20050];int n,m,z,x,y;int find(int x){ if(x==fa[x]) return fa[x]; else return fa[x]=find(fa[x]);}void merge(int x,int y){ x=find(x),y=find(y); fa[x]=y;}int main(){ scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) fa[i]=i; for(int i=1;i<=m;i++){ scanf("%d%d%d",&z,&x,&y); if(z==1) merge(x,y); else { if(find(x)==find(y)) printf("Y\n"); else printf("N\n"); } } return 0;}
倍增lca
http://codevs.cn/problem/2370/
核心代码void dfs(int x,int f){//预处理 fa[0][x]=f; dep[x]=dep[f]+1; for(int i=fst[x];i!=-1;i=nxt[i]){ int v=e[i].t; if(v==f) continue; dis[v]=dis[x]+e[i].v; dfs(v,x); } return ;}void make_lca(){//倍增求父亲 for(int j=1;j<=20;j++){ for(int i=0;i<n;i++) fa[j][i]=fa[j-1][fa[j-1][i]]; }}int lca(int x,int y){//查询x y的lca if(dep[x]<dep[y]) swap(x,y); int dd=dep[x]-dep[y]; for(int j=0;j<=20;j++){ if((1<<j)&(dd)){ x=fa[j][x]; } } if(x==y) return x; for(int j=20;j>=0;j--){ if(fa[j][x]==fa[j][y]) continue; x=fa[j][x],y=fa[j][y]; } return fa[0][x];}
阅读全文
0 0
- NOIP 模板 跪求大佬们指正错误
- 错误,求大佬帮助
- 萌新一只 跪求大佬们相助 关于ubuntu
- Java容器简介-欢迎大佬指正
- 【NOIP模板】 树链剖分 (求lca)
- 绝对大佬的模板%%%
- 微信小程序细节坑(自己刚开始做小程序中遇到的一些细节,如有错误,还请大佬指正,看心情更新。。。。)
- 20171216区间dp(有错请各位大佬指正)
- NOIP模板
- 一目了然读书笔记,求高手指正
- 求大佬看看在bmp截图中的错误 以下为截图
- 指正
- 在大学老师布置的一些题目,欢迎各位大佬指正(1)
- 在大学老师布置的一些题目,欢迎各位大佬指正(2)
- 在大学老师布置的一些题目,欢迎各位大佬指正(3)
- 在大学老师布置的一些题目,欢迎各位大佬指正(4)
- 在大学老师布置的一些题目,欢迎各位大佬指正(5)
- 在大学老师布置的一些题目,欢迎各位大佬指正(6)
- Python并行计算pp模块实践笔记
- 小猪的C语言快速入门系列(四)
- JSON数据格式学习
- Kubernetes集群中部署dashboard
- ArcGIS API for JavaScript 离线地图调用源码示例功能
- NOIP 模板 跪求大佬们指正错误
- 文章标题
- bootstrap 多重模态框 滚动条消失问题
- sdnu1039
- MP算法与OMP算法
- git命令行常用操作
- Spring Boot 使用 Thymeleaf模板
- 使用NotePad++查看16进制的文件
- 二分查找的JAVA实现