1.最短路方案数 (边权为1用这个模板)
(图论中的DP,由于BFS天生具有拓扑序,所以可以DP)
acwing 1134 最短路计数
可以发现这里的BFS没有用st[]数组,
直接遍历邻点进行更新
#include <bits/stdc++.h>
using namespace std;
const int N=1e5+10;
const int M=4e5+10;
const int mode=1e5+3;
int n,m;
int e[M],ne[M],h[N],idx;
int dis[N],cnt[N]; //核心就在于多了cnt[]
/*
dis[]记录的是1~i的所有路径中最短的
cnt[]记录的是最短路(最优解)的条数(方案数)
*/
int q[N];
void add(int a,int b)
{
e[idx]=b;
ne[idx]=h[a];
h[a]=idx++;
}
void bfs()
{
memset(dis,0x3f,sizeof dis);
dis[1]=0;
cnt[1]=1;
int hh=0,tt=0;
q[0]=1;
//本题没有st[]数组的参与
while(hh<=tt)
{
int t=q[hh++];
for(int i=h[t];i!=-1;i=ne[i])
{
int j=e[i];
if(dis[j]>dis[t]+1)
{
dis[j]=dis[t]+1;
cnt[j]=cnt[t]; //最短路数
q[++tt]=j;
}
else if(dis[j]==dis[t]+1) //如果同为最优解(最短路)
{
cnt[j]=(cnt[j]+cnt[t])%mode;
}
}
}
}
int main()
{
int n,m;
scanf("%d%d",&n,&m);
memset(h,-1,sizeof h);
while(m--)
{
int a,b;
scanf("%d%d",&a,&b);
add(a,b);
add(b,a);
}
bfs();
for(int i=1;i<=n;i++) //从1到顶点i有多少条不同的最短路
{
printf("%d\n",cnt[i]);
}
return 0;
}
2.双端队列广搜 求最短路 (边权为0或1用这个模板)
注意双端队列广搜:
1.多了个st[]数组,和迪杰一样的用法,
2.双端队列的定义
3.新加的边长是1就加入队尾
新加的边长是0就加入队头
#include <iostream>
#include <cmath>
#include <cstring>
#include <deque> //定义一个双端队列
#define x first
#define y second
using namespace std;
const int N=510;
typedef pair<int,int> PII;
int r,c;
char map[N][N];
int dis[N][N]; //要旋转的边权为1,不要旋转的边权为0
bool st[N][N]; //迪杰特斯拉相似的算法必须开标记数组
int dx[4]={-1,-1,1,1}; //格子顶点之间的转换
int dy[4]={-1,1,1,-1};
int ix[4]={-1,-1,0,0}; //基于一个顶点坐标可能走通的斜杠的编号变换
int iy[4]={-1,0,0,-1};
char a[]="\\/\\/"; //表明当前中心的顶点到四个方向能走通的,就是没有断的
int bfs()
{
deque<PII> q;
memset(dis,0x3f,sizeof dis);
q.push_back({0,0});
//始终牢记,只有出队后才能把标记数组置TRUE
dis[0][0]=0;
while(q.size())
{
auto t=q.front();
q.pop_front();
if(st[t.x][t.y])
continue;
st[t.x][t.y]=true;
//if(t.x==r&&t.y==c)
//return dis[t.x][t.y];
for(int i=0;i<4;i++)
{
int xx=t.x+dx[i];
int yy=t.y+dy[i];
if(xx<0||xx>r||yy<0||yy>c) //格点的顶点坐标是要比字符的边界还要多1的
{
continue;
}
//所示字符在字符数组的下标
int mx=t.x+ix[i];
int my=t.y+iy[i];
int d=dis[t.x][t.y]+(map[mx][my]!=a[i]); //要旋转的边权为1,就加1,反之走通不需要旋转加0
if(d<dis[xx][yy])
{
dis[xx][yy]=d;
if(map[mx][my]!=a[i])
q.push_back({xx,yy});
else q.push_front({xx,yy});
}
}
}
return dis[r][c];
}
int main()
{
int t;
cin>>t;
while(t--)
{
cin>>r>>c;
memset(st,false,sizeof st);
for(int i=0;i<r;i++)
scanf("%s",map[i]);
int t=bfs(); //必须要开个变量来存这个返回值
if(t==0x3f3f3f3f)
printf("NO SOLUTION\n");
else printf("%d\n",t);
}
}