蓝桥
Trie树
存储字符串
查询字符串出现了多少次
模板
#include<iostream>
using namespace std;
const int N=100010;
int son[N][26]; //存每个点的所有儿子 N当前节点的下标
int cnt[N]; //以当前这个点结尾的单词有多少个
int idx; // 当前 用到了哪个下标 ,下标是0的点,既是根节点,又是空节点
char str[N];
void insert(char str[])
{
int p=0;
for(int i=0;str[i];i++)
{
int u=str[i]-'a';
if(!son[p][u]) son[p][u]=++idx;
p=son[p][u];
}
cnt[p]++;
}
int query(char str[])
{
int p=0;
for(int i=0;str[i];i++)
{
int u=str[i]-'a';
if(!son[p][u]) return 0;
p=son[p][u];
}
return cnt[p];
}
int main()
{
int n;
scanf("%d",&n);
while(n--)
{
char op[2]; //通过字符串来读
scanf("%s%s",&op,&str); //%s 自动过滤空格回车
if(op[0]=='I') insert(str);
else printf("%d\n",query(str));
}
}
最大异或对
在给定的N个整数A1,A2.。。。An中选出两个进行异或运算,得到的结果最大是多少?
输入格式
第一行输入一个整数N
第二行输入N个整数A~An
输出格式
输出一个整数表示答案
数据范围
1<=N<=1e5
0<=Ai<2e31
输入样例
3
1 2 3
输出样例
3
#include<iostream>
#include<cstring>
using namespace std;
const int N=100010,M=31*N;
int n;
int a[N];
int son[M][2],idx;
void insert(int x)
{
int p=0;
for(int i=30;i>=0;i--)
{
int u=x>>i&1;
if(!son[p][u]) son[p][u] =++idx;
p=son[p][u];
}
}
int query(int x)
{
int p=0,res=0;
for(int i=30;i>=0;i--)
{
int u=x>>i&1;
if(son[p][!u])
{
p=son[p][u];
res=res*2+ !u;
}
else
{
p=son[p][u];
res=res*2+u;
}
}
return res;
}
int main()
{
cin>>n;
for(int i=0;i<n;i++) scanf("%d",&a[i]);
int res=0;
for(int i=0;i<n;i++)
{
insert(a[i]);
int t=query(a[i]);
res=max(res,a[i]^t);
}
printf("%d\n",res);
return 0;
}
Tire字符串统计
最大异或和
BFS
微博转发
全球气候变暖
走迷宫
0为通路
输入
5 5
0 1 0 0 0
0 1 0 1 0
0 0 0 0 0
0 1 1 1 0
0 0 0 1 0
输出
8
#include <iostream>
#include<algorithm>
#include<cstring>
#include<queue>
using namespace std;
typedef pair<int,int>PII;
const int N=110;
int n,m;
int g[N][N];
int d[N][N];
PII q[N*N];
int bfs()
{
int hh=0,tt=0;
q[0]={0,0};
memset(d,-1,sizeof d);
d[0][0]=0;
int dx[4]={-1,0,1,0},dy[4]={0,1,0,-1};
while(hh<=tt)
{
auto t=q[hh++];
for(int i=0;i<4;i++)
{
int x=t.first+dx[i],y=t.second+dy[i];
if(x>=0&&x<n&&y>=0&&y<m&&g[x][y]==0&&d[x][y]==-1)
{
d[x][y]=d[t.first][t.second]+1;
q[++tt]={x,y};
}
}
}
return d[n-1][m-1];
}
int main()
{
cin>>n>>m;
for(int i=0;i<n;i++)
for(int j=0;j<m;j++)
cin>>g[i][j];
cout<<bfs()<<endl;
}
输出路径(倒叙)
4 4
3 4
2 4
2 3
2 2
2 1
2 0
1 0
8
#include <iostream>
#include<algorithm>
#include<cstring>
#include<queue>
using namespace std;
typedef pair<int,int>PII;
const int N=110;
int n,m;
int g[N][N];
int d[N][N];
PII q[N*N],Prev[N][N];
int bfs()
{
int hh=0,tt=0;
q[0]={0,0};
memset(d,-1,sizeof d);
d[0][0]=0;
int dx[4]={-1,0,1,0},dy[4]={0,1,0,-1};
while(hh<=tt)
{
auto t=q[hh++];
for(int i=0;i<4;i++)
{
int x=t.first+dx[i],y=t.second+dy[i];
if(x>=0&&x<n&&y>=0&&y<m&&g[x][y]==0&&d[x][y]==-1)
{
d[x][y]=d[t.first][t.second]+1;
Prev[x][y]=t;
q[++tt]={x,y};
}
}
}
int x=n-1,y=m-1;
while(x||y)
{
cout<<x<<" "<<y<<endl;
auto t=Prev[x][y];
x=t.first,y=t.second;
}
return d[n-1][m-1];
}
int main()
{
cin>>n>>m;
for(int i=0;i<n;i++)
for(int j=0;j<m;j++)
cin>>g[i][j];
cout<<bfs()<<endl;
}
八数码
全球变暖
DFS
不同路径数
排列数字
输入
3
输出
1 2 3
1 3 2
2 1 3
2 3 1
3 1 2
3 2 1
#include <iostream>
#include<algorithm>
using namespace std;
const int N=10;
int path[N];
bool st[N];
int n;
void dfs(int u)
{
if(u==n)
{
for(int i=0;i<n;i++) cout<<path[i]<<" ";
cout<<endl;
return ;
}
for(int i=1;i<=n;i++)
{
if(!st[i])
{
path[u]=i;
st[i]=true;
dfs(u+1);
st[i]=false;//恢复现场
}
}
}
int main()
{
cin>>n;
dfs(0);
}
n-皇后问题
输入
4
输出
.Q…
…Q
Q…
…Q.
…Q.
Q…
…Q
.Q…
#include <iostream>
#include<algorithm>
using namespace std;
const int N=20;
char g[N][N];
bool col[N],dg[N],udg[N];
int n;
void dfs(int u)
{
if(n==u)
{
for(int i=0;i<n;i++) puts(g[i]);
puts("");
return ;
}
for(int i=0;i<n;i++)
if(!col[i]&&!dg[u+i]&&!udg[n-u+i]) //截距b=y-x
// b=y+x
{
g[u][i]='Q';
col[i]=dg[u+i]=udg[n-u+i]=true;
dfs(u+1);
col[i]=dg[u+i]=udg[n-u+i]=false;
g[u][i]='.';
}
}
int main()
{
cin>>n;
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
g[i][j]='.';
dfs(0);
}
小猫爬山
带分数
拓扑排序
构造有向无环图
有向图的拓扑排序
最短路
Dijkstra
Dijkstra求最短路I
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
const int N=510;
int n,m;
int g[N][N];
int dist[N];
bool st[N];
int dijkstra()
{
//初始化距离
memset(dist,0x3f,sizeof dist);
dist[1]=0;
//迭代n次 ,先找最小值 ,当前没有确定最短路长度的所有点中距离最小的
for(int i=0;i<n;i++)
{
int t=-1; //还没有确定最短路
//遍历所有点
for(int j=1;j<=n;j++)
if(!st[j]&&(t==-1||dist[t]>dist[j]))
t=j;
st[t]=true; //把t加到集合里
for(int j=1;j<=n;j++)
dist[j]=min(dist[j],dist[t]+g[t][j]); //更新1~j的长度
}
if(dist[n]==0x3f3f3f3f) return -1; //不存在 ,1和n不连通
return dist[n];
}
int main()
{
cin>>n>>m;
//初始化邻接矩阵
memset(g,0x3f,sizeof g);
while(m--)
{
int a,b,c;
cin>>a>>b>>c;
g[a][b]=min(g[a][b],c); //a和b之间的边保留长度最短的那条边
}
int t=dijkstra();
cout<<t<<endl;
return 0;
}
Dijkstra求最短路II——堆优化
#include<iostream>
#include<algorithm>
#include<cstring>
#include<queue>
using namespace std;
typedef pair<int,int> PII;
const int N=100010;
int n,m;
int h[N],e[N],ne[N],w[N];
int dist[N];
bool st[N];
int idx;
void add(int a,int b,int c)
{
e[idx]=b,w[idx]=c,ne[idx]=h[a],h[a]=idx++;
}
int dijkstra()
{
//初始化距离
memset(dist,0x3f,sizeof dist);
dist[1]=0;
priority_queue<PII,vector<PII>,greater<PII>>heap;
heap.push({0,1});
while(heap.size())
{
auto t=heap.top();
heap.pop();
int ver=t.second,distance=t.first;
if(st[ver]) continue;
for(int i=h[ver];i!=-1;i=ne[i])
{
int j=e[i];
if(dist[j]>distance+w[i])
{
dist[j]=distance+w[i];
heap.push({dist[j],j});
}
}
}
if(dist[n]==0x3f3f3f3f) return -1; //不存在 ,1和n不连通
return dist[n];
}
int main()
{
cin>>n>>m;
//初始化邻接表
memset(h,-1,sizeof h);
while(m--)
{
int a,b,c;
cin>>a>>b>>c;
add(a,b,c);
}
int t=dijkstra();
cout<<t<<endl;
return 0;
}
存在负权边——Bellman-Ford
输出 3
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
int n,m,k;
const int N=510,M=10010;
int dist[N],backup[N];
struct Edge{
int a,b,c;
}edges[M];
//不超过k条边
int bellman_ford()
{
memset(dist,0x3f,sizeof dist);
dist[1]=0; //初始化
for(int i=0;i<k;i++)
{
memcpy(backup,dist,sizeof dist);
for(int j=0;j<m;j++) //遍历所有边
{
int a=edges[j].a,b=edges[j].b,c=edges[j].c;
dist[b]=min(dist[b],backup[a]+c);
}
}
if(dist[n]>0x3f3f3f3f/2) return -1;
else return dist[n];
}
int main()
{
cin>>n>>m>>k;
for(int i=0;i<m;i++)
{
int a,b,c;
cin>>a>>b>>c;
edges[i]={a,b,c};
}
int t=bellman_ford();
if(t==-1) puts("impossible");
else cout<<t;
}
多源汇最短路——Floyd算法
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=210;
int dist[N][N],INF=1e9;
int n,m,Q;
void floyd()
{
for(int k=1;k<=n;k++)
for(int i=1;i<=n;i++ )
for(int j=1;j<=n;j++)
dist[i][j]=min(dist[i][j],dist[i][k]+dist[k][j]) ;
}
int main()
{
cin>>n>>m>>Q;
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
if(i==j) dist[i][j]=0;
else dist[i][j]=INF;
while(m--)
{
int a,b,w;
cin>>a>>b>>w;
dist[a][b]=min(dist[a][b],w);
}
floyd();
while(Q--)
{
int a,b;
cin>>a>>b;
if(dist[a][b]>INF/2) puts("impossible");
else
cout<<dist[a][b];
}
}
最短距离
道路与航线
最小生成树
样例二
5 10
1 2 8
2 2 7
2 1 1
3 4 3
4 4 -10
1 3 -9
5 2 -4
3 1 0
1 4 8
4 4 7
输出
-9
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
int n,m;
const int N=1010,INF=0x3f3f3f3f;
int g[N][N],d[N];
bool st[N];
int prim()
{
memset(d,0x3f,sizeof d);
int res=0;
for(int i=0;i<n;i++) //循环n次
{
int t=-1;
for(int j=1;j<=n;j++)
if(!st[j]&&(t==-1||d[t]>d[j]))
t=j;
if(i&&d[t]==INF) return INF;
if(i) res+=d[t];
for(int j=1;j<=n;j++) d[j]=min(d[j],g[t][j]);
st[t]=true;
}
return res;
}
int main()
{
cin>>n>>m;
memset(g,0x3f,sizeof g);
while(m--)
{
int a,b,c;
cin>>a>>b>>c;
g[a][b]=g[b][a]=min(g[a][b],c);
}
int t=prim();
if(t==INF) puts("impossible");
cout<<t<<endl;
}
Kruskal
4 5
1 2 1
1 3 2
1 4 3
2 3 2
3 4 4
输出
6
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=100010;
int n,m,p[N];
struct Edge{
int a,b,w;
bool operator<(const Edge &W) const
{
return w<W.w;
}
}edges[N];
int find(int x)
{
if(x!=p[x]) p[x]=find(p[x]);
return p[x];
}
int main()
{
cin>>n>>m;
for(int i=0;i<m;i++)
{
int a,b,w;
cin>>a>>b>>w;
edges[i]={a,b,w};
}
sort(edges,edges+m);
for(int i=1;i<=n;i++) p[i]=i;//初始化
int res=0,cnt=0;
for(int i=0;i<m;i++)
{
int a=edges[i].a,b=edges[i].b,w=edges[i].w;
a=find(a),b=find(b);
if(a!=b) //不在一个集合
{
p[a]=b;
res+=w;
cnt++;
}
}
if(cnt<n-1) puts("impossible");
else printf("%d\n",res);
}