hdu 1688 Sightseeing

题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=1688

这个题大概意思是求从s出发,到f的最短路和次短路的条数一共有多少条(注:次短路的长度为最短路+1)

解决这个题的办法是:还是开一个二维的数组记录最小值和次小值,和对应的二维数组记录最小值的条数和次小值的条数。其他的和dijkstra做第K短路是差不多,不过还要简单一些,然后统计。

代码如下:
#include<cstdio>
#include<cstring>
#define MAXN 1005
#define Inf 0x3ffffff

using namespace std;

struct edge
{
int e,c,next;
}st[10005];

int num[MAXN][2],fa[MAXN],n,m,S,F;//num中记录最短路和次短路的条数,

void Dij()
{
int dis[MAXN][2],ff[MAXN],i,Min,Minj;//dis记录最小值和次小指(不重复)

for(i=1;i<=n;i++)
{
ff[i]=0;
dis[i][0]=Inf;
dis[i][1]=Inf;
num[i][0]=0;
num[i][1]=0;
}

num[S][0]=1;
dis[S][0]=0;
while(1)
{
Min=Inf;
for(i=1;i<=n;i++)
{
if(ff[i]<2 && dis[i][ff[i]]<Min)
{
Min=dis[i][ff[i]];
Minj=i;
}
}
if(Min==Inf || (Minj==F && ff[F]>0))break;
int f=ff[Minj]++;
for(i=fa[Minj];i;i=st[i].next)
{
int x=st[i].e;
if(ff[x]<2)
{
int M=st[i].c+Min;
if(M<dis[x][ff[x]])
{
if(ff[x]==0)
{
num[x][1]=num[x][0];
dis[x][1]=dis[x][0];
num[x][0]=num[Minj][f];
dis[x][0]=M;
}
else
{
num[x][1]=num[Minj][f];
dis[x][1]=M;
}
}
else if(M==dis[x][ff[x]])
{
num[x][ff[x]]+=num[Minj][f];
}
else if(ff[x]==0)
{
if(st[i].c+Min<dis[x][1])
{
num[x][1]=num[Minj][f];
    dis[x][1]=st[i].c+Min;
}
else if(st[i].c+Min==dis[x][1])
{
num[x][1]+=num[Minj][f];
}
}
}
}
}
if(dis[F][1]==dis[F][0]+1)
num[F][0]+=num[F][1];
printf("%d\n",num[F][0]);
}
void make()
{
int i,now=1,a,b,c;
memset(fa,0,sizeof(fa));
memset(num,0,sizeof(num));
while(m--)
{
scanf("%d%d%d",&a,&b,&c);
st[now].e=b;st[now].c=c;st[now].next=fa[a];fa[a]=now;
now++;
}
scanf("%d%d",&S,&F);
Dij();
}

int main()
{
int t;
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&n,&m);
make();
}
return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值