1.P1144 最短路计数
算法思路:邻接表存图,边权为1,spfa模板
if(dis[to]>dis[u]+mp[u][to]) num[to]=num[u];
else if(dis[to]==dis[u]+mp[u][to]) num[to]=(num[to]+num[u])%mod;
注意重边和自环;在运用spfa进行动态逼近松弛时,如果有一个点能被松驰,则代表有一条新的路径被发现同时整合起来
![](http://img.e-com-net.com/image/info8/b8d97b5613f94ed2ba791cad57d0b2ed.gif)
![](http://img.e-com-net.com/image/info8/2f88dd3f1cd145f59c0e47b51acdbd4b.gif)
#include#include #include #include #include #include using namespace std; const int maxn=1e6+10;const int mod=100003;int n,m,s,e; vector<int>mp[maxn];int dis[maxn],num[maxn],vis[maxn]; void spfa(int s) { memset(dis,0x3f,sizeof(dis)); memset(num,0,sizeof(num)); memset(vis,0,sizeof(vis)); queue<int>q;q.push(s);dis[s]=0,num[s]=1,vis[s]=1; while(!q.empty()) { int nn=q.front();q.pop();vis[nn]=0; for(int i=0;i ) { int t=mp[nn][i]; if(dis[t]>dis[nn]+1) { dis[t]=dis[nn]+1,num[t]=num[nn]; if(!vis[t]){ q.push(t); vis[t]=1; } } else if(dis[t]==dis[nn]+1) { num[t]=(num[t]+num[nn])%mod; if(!vis[t]){ q.push(t); vis[t]=1; } } } } } int main() { scanf("%d%d",&n,&m); for(int i=1;i<=m;i++) { scanf("%d%d",&s,&e); mp[s].push_back(e),mp[e].push_back(s); } spfa(1); for(int i=1;i<=n;i++) printf("%d\n",num[i]); return 0; }
2.P1119 灾后重建
算法思路:这个题在线spfa居然wa了,卡的妙啊;注意题目中给的数据,时间是按照升序的过程进行排序,由此可在时间限制的基础上进行floy,很奇葩
也属于记忆化搜索吧,体现了floyd的动态规划的性质
![](http://img.e-com-net.com/image/info8/b8d97b5613f94ed2ba791cad57d0b2ed.gif)
![](http://img.e-com-net.com/image/info8/2f88dd3f1cd145f59c0e47b51acdbd4b.gif)
#include#include #include #define maxn 210 #define maxm 50010 using namespace std; int n,m,dis[maxn][maxn],t[maxm],q,k; int main() { scanf("%d%d",&n,&m); memset(dis,0x3f,sizeof(dis)); memset(t,0x3f,sizeof(t)); for(int i=0;i ) scanf("%d",&t[i]), dis[i][i]=0; for(int i=1;i<=m;i++) { int a,b,c; scanf("%d%d%d",&a,&b,&c); dis[a][b]=dis[b][a]=c; } scanf("%d",&q); for(int o=1;o<=q;o++) { int a,b,c; scanf("%d%d%d",&a,&b,&c); while(t[k]<=c) { for(int i=0;i ) for(int j=0;j ) dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]); k++; } if(dis[a][b]==0x3f3f3f3f||t[a]>c||t[b]>c) printf("-1\n"); else printf("%d\n",dis[a][b]); } return 0; }
3. P1608 路径统计
算法思路:用cnt数组计数就好,同1,wa1,还是不明白第一个点什莫鬼数据
![](http://img.e-com-net.com/image/info8/b8d97b5613f94ed2ba791cad57d0b2ed.gif)
![](http://img.e-com-net.com/image/info8/2f88dd3f1cd145f59c0e47b51acdbd4b.gif)
#include#include #include #include #include using namespace std; const int INF=0x3f3f3f3f; int num[2100],mp[2100][2100],n,m,x,y,c; void init(int n) { for(int i=0;i<=n;i++) for(int j=0;j<=n;j++) mp[i][j]=(i==j)?0:INF; memset(num,0,sizeof(num)); } int vis[2100];int dis[2100]; void spfa(int s) { fill(dis,dis+n+1,INF); memset(vis,0,sizeof(vis)); queue<int>q; q.push(s);dis[s]=0;vis[s]=1;num[s]=1; while(!q.empty()) { int now=q.front();q.pop();vis[now]=0; for(int i=1;i<=n;i++) { if(now==i) continue; if(dis[i]>dis[now]+mp[now][i]) { dis[i]=dis[now]+mp[now][i]; num[i]=num[now]; if(!vis[i]){ vis[i]=1; q.push(i); } } else if(dis[i]==dis[now]+mp[now][i]) { num[i]=num[i]+num[now]; } } } } int main() { scanf("%d%d",&n,&m);init(n); for(int i=1;i<=m;i++) { scanf("%d%d%d",&x,&y,&c); mp[x][y]=min(mp[x][y],c); } spfa(1); if(dis[n]==INF) printf("No answer"); else printf("%d %d",dis[n],num[n]); return 0; }
4.newcoder 小木乃伊到我家
思路:刘汝佳spfa最短路模板,结构体存路径
![](http://img.e-com-net.com/image/info8/b8d97b5613f94ed2ba791cad57d0b2ed.gif)
![](http://img.e-com-net.com/image/info8/2f88dd3f1cd145f59c0e47b51acdbd4b.gif)
#includeusing namespace std; const int INF=0x3fffffff; const int N=2e5+10; struct node{ int f,t,v; }; vector<int>G[N]; vector edge; void add(int f,int t,int v){ edge.push_back({f,t,v}); edge.push_back({t,f,v}); int m=edge.size(); G[f].push_back(m-2); G[t].push_back(m-1); } int dis[N];int vis[N]; int n,m,from,to,v; void spfa(int s){ for(int i=0;i<=n;i++) vis[i]=0,dis[i]=INF; queue<int>q;vis[s]=1;dis[s]=0;q.push(s); while(!q.empty()){ int u=q.front();q.pop();vis[u]=0; for(int i=0;i ){ int v=G[u][i]; if(dis[edge[v].t]>dis[u]+edge[v].v){ dis[edge[v].t]=dis[u]+edge[v].v; if(!vis[edge[v].t]){ q.push(edge[v].t); vis[edge[v].t]=1; } } } } } int main(){ while(~scanf("%d%d",&n,&m)){ for(int i=1;i<=m;i++){ scanf("%d%d%d",&from,&to,&v); add(from,to,v); } spfa(1); if(dis[n]==INF) printf("qwb baka\n"); else printf("%d\n",dis[n]); } return 0; }
5.hihocoder 1093 最短路
思路:搞清楚了dijkstra和spfa的区别 博客链接 本题运用了dijkstra+优先队列
![](http://img.e-com-net.com/image/info8/b8d97b5613f94ed2ba791cad57d0b2ed.gif)
![](http://img.e-com-net.com/image/info8/2f88dd3f1cd145f59c0e47b51acdbd4b.gif)
#includeusing namespace std; const int N=1e5+10; struct edge{int to,v;}; vector g[N]; const int INF=0x3f3f3f3f; struct node{ int x,y; bool friend operator < (node a,node b){return a.y<b.y;} bool friend operator > (node a,node b){return a.y>b.y;} }; int dis[N]; int spfa(int s,int t){ memset(dis,0x3f,sizeof(dis)); dis[s]=0; priority_queue ,greater >q; q.push({s,0}); while(!q.empty()){ node u=q.top();q.pop(); if(dis[u.x]>u.y) continue; //if(vis[u.x]) continue;vis[u.x]=1; for(int i=0;i ){ edge v=g[u.x][i]; if(dis[v.to]>dis[u.x]+v.v){ dis[v.to]=dis[u.x]+v.v; q.push({v.to,dis[v.to]}); } } } return dis[t]; } int main(){ int n,m,s,t,x,y,v; scanf("%d%d%d%d",&n,&m,&s,&t); for(int i=1;i<=m;i++){ scanf("%d%d%d",&x,&y,&v); g[x].push_back({y,v}); g[y].push_back({x,v}); } int ans=spfa(s,t); printf("%d\n",ans); return 0; }