博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
NOIp知识点复习——最短路计数
阅读量:5111 次
发布时间:2019-06-13

本文共 3239 字,大约阅读时间需要 10 分钟。

$Mingqi\_H$

NOIp 2017考挂了...gg

重新开始好了。

计划明年2月24号前复习完所有的NOIp知识点(毕竟很不熟练啊),之后到七月底前学习完省选的东西(flag?)。

从现在开始吧。

11.29 NOIp图论(Ⅰ)

坑:Floyd、Dijkstra、最短路计数、Tarjan、二分图、拓扑。

最短路计数:

类似一个标准的SPFA,不同之处在于加粗的两句:

  • 如果第一次到达nxt节点,nxt节点的最短路数量就等于其前驱节点的最短路数量,当前点需要松弛,则当前点继承被松弛节点的最短路条数,更新一波距离,丢到队列里。
  • 否则当到nxt的最短路长度等于到其前驱点的最短路+当前边的权值时,到nxt点的最短路数量应该加上到其前驱节点的最短路数量(再次更新)。

例题:洛谷P1144,P1608,P3953前30%。

#include
#include
#include
using namespace std;const int maxn=1e5+10;struct Edge{
int u,v,w;}edge[2*maxn];int head[maxn],cnt;void add(int u,int v,int w){edge[++cnt].u=head[u],edge[cnt].v=v,edge[cnt].w=w,head[u]=cnt;}int dis[maxn],vis[maxn];int ans[maxn];inline void spfa(int s){ queue
q;int cur,nxt; memset(dis,0x7f,sizeof(dis)),memset(vis,0,sizeof(vis)); dis[s]=0,vis[s]=1,q.push(s); ans[s]=1; while(!q.empty()) { cur=q.front(),vis[cur]=0,q.pop(); for(int i=head[cur];i;i=edge[i].u) { nxt=edge[i].v; if(!ans[nxt])ans[nxt]=ans[cur],dis[nxt]=dis[cur]+edge[i].w,q.push(nxt); else if(dis[nxt]==dis[cur]+edge[i].w)ans[nxt]+=ans[cur],ans[nxt]%=mod; } }}
View Code

 以上代码似乎是错误的。gg。

P1608

#include
#include
#include
using namespace std;const int N = 2200;int head[N];struct node{ int v,w,next;}edge[N*N/2];int n,e,num=0,dis[N];bool vis[N];void add_edge(int x,int y,int z){ edge[++num].v=y;edge[num].w=z;edge[num].next=head[x];head[x]=num;}int ans1,cnt[N];int minn=0;void spfa(int x){ queue
que; vis[1]=1;dis[1]=0;cnt[1]=1; que.push(1); while(!que.empty()) { int u=que.front();que.pop(); if(u==n)continue; for(int i=head[u];i;i=edge[i].next) { int v=edge[i].v; if(dis[u]+edge[i].w
View Code

 啊...原来是题目有锅。。。代码没什么问题。

P3953前30%:

#include
#include
#include
using namespace std;const int maxn=100000+10;struct Edge{
int u,v,w;} edge[2*maxn];int head[maxn],c;void add(int u,int v,int w){edge[++c].u=head[u],edge[c].v=v,edge[c].w=w,head[u]=c;}int n,m,x,y,z,k,p,t;int dis[maxn],cnt[maxn],vis[maxn];int cur,v;void spfa(int s){ memset(dis,0x3f,sizeof(dis)),memset(cnt,0,sizeof(cnt)),memset(vis,0,sizeof(vis)); queue
q; q.push(s),dis[s]=0,cnt[s]=1; while(!q.empty()) { cur=q.front(),q.pop(),vis[cur]=0; if(cur==n)continue; for(int i=head[cur]; i; i=edge[i].u) { v=edge[i].v; if(dis[cur]+edge[i].w==dis[v])cnt[v]=(cnt[v]+cnt[i])%p; if(dis[cur]+edge[i].w
View Code

由此我们可以得到一般的最短路计数的模板。

void spfa(int s){    memset(dis,0x3f,sizeof(dis)),memset(cnt,0,sizeof(cnt)),memset(vis,0,sizeof(vis));    queue
q; q.push(s),dis[s]=0,cnt[s]=1; while(!q.empty()) { cur=q.front(),q.pop(),vis[cur]=0; if(cur==n)continue; for(int i=head[cur]; i; i=edge[i].u) { v=edge[i].v; if(dis[cur]+edge[i].w==dis[v])cnt[v]+=cnt[i]; if(dis[cur]+edge[i].w

就是一个普通SPFA加了点东西。

转载于:https://www.cnblogs.com/TheRoadToAu/p/7859021.html

你可能感兴趣的文章
CocoaPods的安装和使用那些事(Xcode 7.2,iOS 9.2,Swift)
查看>>
Android 官方新手指导教程
查看>>
幸运转盘v1.0 【附视频】我的Android原创处女作,请支持!
查看>>
UseIIS
查看>>
集合体系
查看>>
vi命令提示:Terminal too wide
查看>>
引用 移植Linux到s3c2410上
查看>>
人与人之间的差距是从大学开始的
查看>>
MySQL5.7开多实例指导
查看>>
hdu 1029 Ignatius ans the Princess IV
查看>>
JAVA学习札记
查看>>
[UOJ] #78. 二分图最大匹配
查看>>
[51nod] 1199 Money out of Thin Air #线段树+DFS序
查看>>
poj1201 查分约束系统
查看>>
简明Linux命令行笔记:chmod
查看>>
简明Linux命令行笔记:tar
查看>>
Red and Black(poj-1979)
查看>>
分布式锁的思路以及实现分析
查看>>
vue v-for下图片src显示失败,404错误
查看>>
腾讯元对象存储之文件删除
查看>>