HDU1688-POJ3463-Sightseeing

(有任何问题欢迎留言或私聊 && 欢迎交流讨论哦

题意:HDU POJ

 原题目描述在最下面。
 求出最短路和次短路的条数,当次短路比最短路长度小1时,输出条数之和,反之输出最短路条数。

思路:

dis1[],cnt1[],dis2[],cnt2[] d i s 1 [ ] , c n t 1 [ ] , d i s 2 [ ] , c n t 2 [ ] 分别表示最短路的长度和条数,次短路的长度和条数。
 当当前距离小于当前点最短路长度的时候,更新二者长度和条数。
 当当前距离等于当前点最短路长度的时候,更新最短路条数。
 当当前距离小于当前点次短路长度的时候,更新次短路的长度和条数。
 当当前距离等于当前点次短路长度的时候,更新次短路的条数。

push p u s h 进队列的时候要标注 push p u s h 进去的是最短路还是次短路。

AC代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<map>
#include<queue>
#include<set>
#include<string>
#include<cmath>
#define lson rt<<1
#define rson rt<<1|1
#define lowbit(x) (x)&(-(x))
#define iis std::ios::sync_with_stdio(false)
using namespace std;
typedef long long LL;
const int N = 1005;
const LL INF = 0x3f3f3f3f3f3f3f3f;
struct lp{
    int to, id;
    LL w;
    lp(int a,LL b){to=a;w=b;id=0;}
    lp(int a,LL b,int c){to=a;w=b;id=c;}
    bool operator <(const lp &a)const {
        if(w!=a.w) return w>a.w;
        return to>a.to;
    }
};
vector<lp>mp[N];
LL dis1[N],dis2[N];
int n, m, pre[N],cnt1[N], cnt2[N], vis[N][3];
int t1,st,ed;
void init(){
    for(int i=0;i<=n;++i)mp[i].clear();
}
void dij(){
  priority_queue<lp>Q;
  Q.push(lp(st,0,1));
  memset(cnt1,0,sizeof(cnt1));
  memset(cnt2,0,sizeof(cnt2));
  memset(vis,0,sizeof(vis));
  memset(dis1,0x3f,sizeof(dis1));
  memset(dis2,0x3f,sizeof(dis2));
  cnt1[st]=1;
  dis1[st]=0;
  while(!Q.empty()){
    lp aa = Q.top();Q.pop();
    int u = aa.to, len = mp[u].size();
    if(vis[u][aa.id])continue;
    vis[u][aa.id] = 1;
    for(int i=0;i<len;++i){
      int v = mp[u][i].to;
      LL w = mp[u][i].w + aa.w;
      //printf("*%d %d %lld %lld %d %d\n", u, v, aa.w, w, cnt1[u], cnt2[u]);
      if(w<dis1[v]){
        dis2[v] = dis1[v];
        cnt2[v] = cnt1[v];
        dis1[v] = w;
        if(aa.id==1)cnt1[v] = cnt1[u];
        else cnt1[v] = cnt2[u];   
        Q.push(lp(v, dis1[v], 1));
        Q.push(lp(v, dis2[v], 2));
      }else if(w == dis1[v]){
        if(aa.id==1)cnt1[v] += cnt1[u];
        else cnt1[v] += cnt2[u];
        //Q.push(lp(v, dis1[v], 1));
      }else if(w < dis2[v]){
        dis2[v] = w;
        if(aa.id==1)cnt2[v] = cnt1[u];
        else cnt2[v] = cnt2[u];  
        Q.push(lp(v, dis2[v], 2));
      }else if(w==dis2[v]){
        if(aa.id==1)cnt2[v] += cnt1[u];
        else cnt2[v] += cnt2[u];
        //Q.push(lp(v, dis2[v], 2)); 
      }
    }
  }
  if(dis1[ed]==dis2[ed]-1)cnt1[ed]+=cnt2[ed];
  printf("%d\n", cnt1[ed]);
}
int main(){
  int t,a,b;
  LL c;
  scanf("%d",&t);
  while(t--){
    scanf("%d%d",&n,&m);
    init();
    for(int i=0;i<m;++i){
      scanf("%d%d%lld",&a,&b,&c);
      mp[a].push_back(lp(b,c));
      //mp[b].push_back(lp(a,c));
    }
    scanf("%d%d", &st,&ed);
    dij();
  }
  return 0;
}


原题目描述:

这里写图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值