NOIp知识点复习——最短路计数
$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<queue>
#include<cstdio>
#include<cstring>
using namespace std;
const int maxn=1e5+;
struct Edge{int u,v,w;}edge[*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<int>q;int cur,nxt;
memset(dis,0x7f,sizeof(dis)),memset(vis,,sizeof(vis));
dis[s]=,vis[s]=,q.push(s);
ans[s]=;
while(!q.empty())
{
cur=q.front(),vis[cur]=,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;
}
}
}
以上代码似乎是错误的。gg。
P1608
#include<cstdio>
#include<queue>
#include<cstring>
using namespace std;
const int N = ;
int head[N];
struct node{
int v,w,next;
}edge[N*N/];
int n,e,num=,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=;
void spfa(int x)
{
queue<int>que;
vis[]=;dis[]=;cnt[]=;
que.push();
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<dis[v])
{
if(dis[u]+edge[i].w<dis[v])
{
dis[v]=dis[x]+edge[i].w;
cnt[v]=cnt[u];
}
if(!vis[v])que.push(v),vis[v]=;
}
else if(dis[u]+edge[i].w==dis[v]) cnt[v]+=cnt[u];
}
vis[u]=;cnt[u]=;
}
}
int main()
{
memset(dis,0x3f,sizeof dis);
scanf("%d%d",&n,&e);
int a,b,c;
for(int i=;i<=e;i++)
{
scanf("%d%d%d",&a,&b,&c);
add_edge(a,b,c);
}
spfa();
if(dis[n]==0x3f3f3f3f)
puts("No Answer");
else printf("%d %d\n",dis[n],cnt[n]);
return ;
}
啊...原来是题目有锅。。。代码没什么问题。
P3953前30%:
#include<queue>
#include<cstdio>
#include<cstring>
using namespace std;
const int maxn=+;
struct Edge{int u,v,w;} edge[*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,,sizeof(cnt)),memset(vis,,sizeof(vis));
queue<int>q;
q.push(s),dis[s]=,cnt[s]=;
while(!q.empty())
{
cur=q.front(),q.pop(),vis[cur]=;
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<dis[v])dis[v]=dis[cur]+edge[i].w,cnt[v]=cnt[cur];
if(cnt[v]&&!vis[v])vis[v]=,q.push(v);
}
cnt[cur]=;
}
}
int main()
{
scanf("%d",&t);
while(t--)
{
memset(head,,sizeof(head)),c=,memset(edge,,sizeof(edge));
scanf("%d%d%d%d",&n,&m,&k,&p);
while(m--)scanf("%d%d%d",&x,&y,&z),add(x,y,z);
spfa();
printf("%d\n",cnt[n]);
}
return ;
}
由此我们可以得到一般的最短路计数的模板。
void spfa(int s)
{
memset(dis,0x3f,sizeof(dis)),memset(cnt,,sizeof(cnt)),memset(vis,,sizeof(vis));
queue<int>q;
q.push(s),dis[s]=,cnt[s]=;
while(!q.empty())
{
cur=q.front(),q.pop(),vis[cur]=;
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<dis[v])dis[v]=dis[cur]+edge[i].w,cnt[v]=cnt[cur];
if(cnt[v]&&!vis[v])vis[v]=,q.push(v);
}
cnt[cur]=;
}
}
就是一个普通SPFA加了点东西。
NOIp知识点复习——最短路计数的更多相关文章
- 2018.11.05 NOIP模拟 规避(最短路计数)
传送门 正难则反. 考虑计算两人相遇的方案数. 先正反跑一遍最短路计数. 然后对于一条在最短路上的边(u,v)(u,v)(u,v),如果(dis(s,u)*2<total&&di ...
- Noip知识点备考
作为一个oier,适当的整理是有必要的.蒟蒻根据自己的理解,筛选出考noip应当掌握的知识点.可能后期还有解题思路和模板,先挖个坑慢慢补呗. 60级张炳琪Noip知识点总结 可能是本人比较弱,写的内容 ...
- NOIP系列复习及题目集合
首先是我的酱油记了啦~: Xs的NOIP2014酱油记,持续更新中 知识点方面: noip知识点总结之--贪心 noip知识点总结之--线性筛法及其拓展 noip知识点总结之--欧几里得算法和扩展欧几 ...
- 【SPFA】 最短路计数
最短路计数 [问题描述] 给出一个N个顶点M条边的无向无权图,顶点编号为1-N.问从顶点1开始,到其他每个点的最短路有几条. [输入格式] 输入第一行包含2个正整数N,M,为图的顶点数与边数. ...
- noip知识点总结之--欧几里得算法和扩展欧几里得算法
一.欧几里得算法 名字非常高大上的不一定难,比如欧几里得算法...其实就是求两个正整数a, b的最大公约数(即gcd),亦称辗转相除法 需要先知道一个定理: gcd(a, b) = gcd(b, a ...
- P1144 最短路计数
P1144 最短路计数 题目描述 给出一个N个顶点M条边的无向无权图,顶点编号为1-N.问从顶点1开始,到其他每个点的最短路有几条. 输入输出格式 输入格式: 输入第一行包含2个正整数N,M,为图的顶 ...
- 洛谷P1144最短路计数题解
最短路计数 此题还是寻找从1到i点总共有几个最短路且每条边的边长为1,对于这种寻找最短路的个数,我们可以反向搜索,即先用\(SPFA\)预处理出所有点的最短路,然后我们反向记忆化搜索,可以用\(sum ...
- 洛谷P1144 最短路计数(SPFA)
To 洛谷.1144 最短路计数 题目描述 给出一个N个顶点M条边的无向无权图,顶点编号为1-N.问从顶点1开始,到其他每个点的最短路有几条. 输入输出格式 输入格式: 输入第一行包含2个正整数N,M ...
- 洛谷 P1144 最短路计数 解题报告
P1144 最短路计数 题目描述 给出一个\(N\)个顶点\(M\)条边的无向无权图,顶点编号为\(1-N\).问从顶点1开始,到其他每个点的最短路有几条. 输入输出格式 输入格式: 第一行包含2个正 ...
随机推荐
- “2014年ArcGIS影像高级培训班——5月份北京站”火热报名中!
您从事遥感类的相关工作吗?您正对着一景景影像数据不知从何下手吗?您有TB级甚至更高量级的影像数据须要有效管理.即时分享吗?您须要构建Web端的应用实现影像实时处理.在线分析吗? 您是否已经找到有效的解 ...
- Android:仿手机QQ好友动态的ListView
1.介绍: 本博客使用XListView模仿Android版QQ好友动态的ListView效果.效果截图例如以下: 效果图1 watermark/2/text/aHR0cDovL2Jsb2cuY3Nk ...
- 从零讲Java,给你一条清晰地学习道路!该学什么就学什么!
从零讲JAVA ,给你一条 清晰地学习道路!该学什么就学什么! 1.计算机基础: 1.1数据机构基础: 主要学习:1. ...
- go语言笔记——包的概念本质上和java是一样的,通过大小写来区分private,fmt的Printf不就是嘛!
示例 4.1 hello_world.go package main import "fmt" func main() { fmt.Println("hello, wor ...
- nginx搭建基于http协议的视频点播服务器
1,于由自己的服务器上已经安装好nginx(具体安装方法见我的另一篇文章,Linux中安装nginx),所以不再安装. 2,下载nginx_mod_h264_streaming-2.2.7.tar.g ...
- Spark中统计程序运行时间
import java.text.SimpleDateFormat import java.util.Date val s=NowDate() //显示当前的具体时间 val now=new Date ...
- 2017北京国庆刷题Day1 morning T2
T2火柴棒 (stick) Time Limit:1000ms Memory Limit:128MB 题目描述 众所周知的是,火柴棒可以拼成各种各样的数字.具体可以看下图: 通过2根火柴棒可以拼出 ...
- 洛谷P1396营救(最小生成树)
题目描述 “咚咚咚……”“查水表!”原来是查水表来了,现在哪里找这么热心上门的查表员啊!小明感动的热泪盈眶,开起了门…… 妈妈下班回家,街坊邻居说小明被一群陌生人强行押上了警车!妈妈丰富的经验告诉她小 ...
- android sqlite中判断某个表是否存在
<span style="font-size:18px;">sqlite 中判断某个表是否存在的方法,贴出来供大家参考 /** * 判断某张表是否存在 * @param ...
- servlet.txt笔记
javase jdbc ==>java访问数据库html ==>浏览器显示内容,无法把数据提交给后台?==>动态网页技术(servlet)解决前台.后台交互问题动态网页技术:serv ...