考前算法总结
Posted binghun
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了考前算法总结相关的知识,希望对你有一定的参考价值。
最短路
SPFA
#include <bits/stdc++.h>
using namespace std;
#define N 10001
#define M 500001
struct node{
int to,w,next;
}edge[M];
int cut=0;
int head[N];
int dis[N];
int n,m,k;
bool vis[N];
queue<int> q;
void ini(){
fill(dis+1,dis+N+1,INT_MAX);
memset(head,-1,sizeof(head));
}
void add(int u,int v,int w){//建边
cut++;
edge[cut].w=w;
edge[cut].to=v;
edge[cut].next=head[u];
head[u]=cut;
}
void SPFA(int x){
dis[x]=0;
q.push(x);//头入队
vis[x]=1;
while(!q.empty()){
int u=q.front();q.pop();vis[u]=false;
for(int j=head[u];~j;j=edge[j].next){//调用邻接表
if(dis[edge[j].to]>dis[u]+edge[j].w){
dis[edge[j].to]=dis[u]+edge[j].w;//松弛操作
if(!vis[edge[j].to]){//判断标记
q.push(edge[j].to);//入队边上的点
vis[edge[j].to]=1;//标记
}
}
}
}
}
int main(){
ini();
scanf("%d %d %d",&n,&m,&k);
for(int i=1,u,v,w;i<=m;i++){
scanf("%d %d %d",&u,&v,&w);
add(u,v,w);
}
SPFA(k);
for(int i=1;i<=n;i++){
printf("%d ",dis[i]);
}
return 0;
}
Dijkstra(堆优化)
#include <bits/stdc++.h>
using namespace std;
#define N 10001
#define M 500001
#define P pair<int,int>
#define Fi first
#define Se second
struct node{
int to,w,next;
}edge[M];
int cut=0;
int head[N];
int dis[N];
int n,m,k;
bool vis[N];
priority_queue<P,vector<P>,greater<P> > q;//优先队列
void ini(){
fill(dis+1,dis+N+1,INT_MAX);
memset(head,-1,sizeof(head));
}
void add(int u,int v,int w){
cut++;
edge[cut].w=w;
edge[cut].to=v;
edge[cut].next=head[u];
head[u]=cut;
}
void Dij(int x){
dis[x]=0;
vis[x]=1;
q.push(P(0,x));//头入队
while(!q.empty()){
P u=q.top();q.pop();vis[u.Se]=1;
for(int j=head[u.Se];~j;j=edge[j].next){//邻接表遍历
if(!vis[edge[j].to]&&dis[edge[j].to]>dis[u.Se]+edge[j].w){//判断标记和松弛操作
dis[edge[j].to]=dis[u.Se]+edge[j].w;//松弛
q.push(P(dis[edge[j].to],edge[j].to));//入队
}
}
}
}
int main(){
ini();
scanf("%d %d %d",&n,&m,&k);
for(int i=1,u,v,w;i<=m;i++){
scanf("%d %d %d",&u,&v,&w);
add(u,v,w);
}
Dij(k);
for(int i=1;i<=n;i++){
printf("%d ",dis[i]);
}
return 0;
}
最小生成树
Kruskal
#include <bits/stdc++.h>
using namespace std;
#define N 5001
#define M 200001
struct node{
int u,v,w;
}edge[M];
int fa[N],n,m;
int find(int x){//并查集找爸爸
return fa[x]==x?x:fa[x]=find(fa[x]);
}
void un(int x,int y){//并查集连接
x=find(x);
y=find(y);
fa[x]=y;
}
void ini(){//初始化
for(int i=1;i<=5000;i++)fa[i]=i;
}
bool cmp(node a,node b){
return a.w<b.w;
}
int main(){
ini();
scanf("%d %d",&n,&m);
for(int i=1;i<=m;i++){
scanf("%d %d %d",&edge[i].u,&edge[i].v,&edge[i].w);
}
sort(edge+1,edge+m+1,cmp);
int k=0;
int ans=0;
for(int i=1;i<=m;i++){
if(find(edge[i].u)!=find(edge[i].v)){//判断是否在一个集合里
un(edge[i].u,edge[i].v);
k++;
ans+=edge[i].w;//累加答案
}
if(k==n-1)break;
}
if(k==n-1)printf("%d",ans);
else printf("orz");//不连通
return 0;
}
排序
归并排序(求逆序对)
#include<bits/stdc++.h>
using namespace std;
int n;
int ans=0;
int v[500001];
int t[500001];
void Qsort(int l,int r){//归并
if(l==r)return ;
int mid=(l+r)>>1;
Qsort(1,mid);
Qsort(mid+1,r);//递归
int i=l;int j=mid+1;int k=l;
while(i<=mid&&j<=r){
if(v[i]<=v[j])t[k++]=v[i++];
else t[k++]=v[j++],ans+=mid-i+1;//数学规律
}
while(i<=mid)t[k++]=v[i++];
while(j<=r)t[k++]=v[j++];
for(int i=l;i<=r;i++)v[i]=t[i];
}
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++)scanf("%d",&v[i]);
Qsort(1,n);
printf("%d",ans);
return 0;
}
数据结构
树状数组(区间查询,区间修改)
#include<bits/stdc++.h>
using namespace std;
int a[500001],b[500001],c[500001];
int n,m;
int lowbit(int x){
return x&(-x);
}
void updata(int i,int k){
int x=i;
while(i<=n){
c[i]+=k;
b[i]+=k*(x-1);
i+=lowbit(i);
}
}
int getsum(int i){
int sum=0,x=i;
while(i>0){
sum+=x*c[i]-b[i];
i-=lowbit(i);
}
return sum;
}
//1:区间修改,2:区间查询
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
updata(i,a[i]-a[i-1]);
}
for(int i=1,d,x,y,z;i<=m;i++){
scanf("%d",&d);
if(d==1){
scanf("%d%d%d",&x,&y,&z);
updata(x,z);
updata(y+1,-z);
}else{
scanf("%d%d",&x,&y);
printf("%d
",getsum(y)-getsum(x-1));
}
}
return 0;
}
以上是关于考前算法总结的主要内容,如果未能解决你的问题,请参考以下文章