F - Sightseeing

传送门: POJ - 3463

分析

一句话题意:给你一个有向图,可能有重边,让你求从s到t最短路的条数,如果次短路的长度比最短路的长度多1,那么在加上次短路的条数。

这道题唯一要注意的就是次短路的求法

首先题目中说从起点到终点至少有一条路径,所以我们就不用考虑不可达的情况

我们先考虑如果a到b有一条边,b到c有一条边

那么a到c经过b的路程中次短路只有两种选择,一种是a到b的最短路+b到c的次短路,另一种是a到b的次短路+b到c的次短路

所以我们只需要记录次短路和最短路两个值就可以了

然后我们去跑dij,每次加上一条边会有四种情况对答案产生影响

1.比最短路短

如果之前的最短路不为无穷大的话,我们就把原先最短路的值赋值给原先次短路的值,同时把次短路的数量更新为原先最短路的数量

再更新最短路,同时要把最短路的数量改为到达上一个节点的方案数

2.和最短路一样短

把最短路的数量加一

3.比次短路短

更新次短路的长度,同时要把次短路的数量改为到达上一个节点的方案数

4.和次短路一样长

把次短路的数量加一

代码

#include<cstdio>
#include<algorithm>
#include<cmath>
#include<queue>
#include<cstring>
using namespace std;
const int maxd=1005,maxb=20005;
int head[maxd],tot=1;
struct asd{
int from,to,next,val;
}b[maxb];
void ad(int aa,int bb,int cc){
b[tot].from=aa;
b[tot].to=bb;
b[tot].val=cc;
b[tot].next=head[aa];
head[aa]=tot++;
}
struct jie{
int num,dis,jud;
jie(int aa=0,int bb=0,int cc=0){
num=aa,dis=bb,jud=cc;
}
bool operator < (const jie& A) const{
return dis>A.dis;
}
};
priority_queue<jie> q;
int dis[maxd][3],cnt[maxd][3];
bool vis[maxd][3];
void dij(int xx){
memset(dis,0x3f,sizeof(dis));
memset(cnt,0,sizeof(cnt));
memset(vis,0,sizeof(vis));
dis[xx][0]=0,cnt[xx][0]=1;
q.push(jie(xx,0,0));
while(!q.empty()){
int now=q.top().num;
int judd=q.top().jud;
q.pop();
if(vis[now][judd]) continue;
vis[now][judd]=1;
for(int i=head[now];i!=-1;i=b[i].next){
int u=b[i].to;
int ndis=dis[now][judd]+b[i].val;
if(ndis<dis[u][0]){
if(dis[u][0]!=0x3f3f3f3f){
dis[u][1]=dis[u][0];
cnt[u][1]=cnt[u][0];
q.push(jie(u,dis[u][0],1));
}
dis[u][0]=ndis;
cnt[u][0]=cnt[now][judd];
q.push(jie(u,ndis,0));
}
else if(ndis==dis[u][0]){
cnt[u][0]+=cnt[now][judd];
}
else if(ndis==dis[u][1]){
cnt[u][1]+=cnt[now][judd];
}
else if(ndis<dis[u][1]){
dis[u][1]=ndis;
cnt[u][1]=cnt[now][judd];
q.push(jie(u,ndis,1));
}
}
}
}
int main(){
int t;
scanf("%d",&t);
while(t--){
memset(head,-1,sizeof(head));
memset(&b,0,sizeof(struct asd));
tot=1;
int n,m;
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++){
int aa,bb,cc;
scanf("%d%d%d",&aa,&bb,&cc);
ad(aa,bb,cc);
}
int qd,zd;
scanf("%d%d",&qd,&zd);
dij(qd);
int ans=cnt[zd][0];
if(dis[zd][0]==dis[zd][1]-1) ans+=cnt[zd][1];
printf("%d\n",ans);
}
return 0;
}

最新文章

  1. linux 无交互添加用户设置密码
  2. keras 入门之 regression
  3. OpenJudge计算概论-校门外的树
  4. js实现网页图片延时加载的原理和代码 提高网站打开速度
  5. iOS 对网络视频采集视频截图
  6. Smartcard CA智能卡之调试
  7. STL源码剖析 迭代器(iterator)概念与编程技法(三)
  8. PHP之验证码代码
  9. spring 多线程 写入数据库 和 写入 xml文件
  10. 【转载】ASP.NET中Server.MapPath方法获取网站根目录总结
  11. sklearn使用——最小二乘法
  12. java加载类的顺序
  13. 理解AJAX的原理
  14. [skill][c] *(char**)
  15. 猜字母游戏(Java)
  16. 循环神经网络-Dropout
  17. Android Socket通信详解
  18. Java——File类成员方法
  19. vi和vim的三种模式
  20. JS实现图的创建和遍历

热门文章

  1. 实验五 shell脚本编程
  2. [computer graphics]简单光照模型(Phong和Blinn-Phong)和明暗处理
  3. 一台电脑如何使用多个git账号?
  4. v-on 缩写
  5. Memory layout
  6. 小球(总结sort和cmp函数、结构体排序)
  7. controller场景设计
  8. Jenkins登录无效
  9. Hexo快速构建个人小站-Hexo初始化和将项目托管在Github(一)
  10. RocketMQ系列(七)事务消息(数据库|最终一致性)