POJ 3462 Sightseeing

本文深入探讨了Dijkstra算法的应用,特别是在求解图中两点间最短路径问题时的巧妙运用,并通过具体实例展示了如何计算最短路径及次短路径的数量。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


题意:
给定一张有向图,求图中的最短路和比最短路长度大1的路径的条数


分析:
感觉这道题诠释了dijkstra算法的精髓,(⊙o⊙)…
dis[i][0]代表i点到s的最短路径,dis[i][1]代表i到s的次短路
num[i][0]&num[i][1]同理,vis[i][0]&vis[i][1]同理
当我们在求最短路的时候,每次取队首来更新与他相连的节点的最短路径,求次短路同理
当tmp(队首的更新值)小于最短路时,更新最短路和次短路
等于最短路时更新最短路数量
大于最短路小于次短路时更新次短路
等于次短路时更新次短路数量


代码如下:

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<queue>
#define inf 0x3f3f3f3f
using namespace std;
const int maxn=1000+5,maxm=10000+5;
int cas,n,m,s,e,cnt,hd[maxn],to[maxm],nxt[maxm],w[maxm],dis[maxn][2],num[maxn][2];
bool vis[maxn][2];
struct lala{
    int id,flag;
    lala(int idd,int f){
        id=idd,flag=f;
    }
    friend bool operator < (lala a,lala b){
        return dis[a.id][a.flag]>dis[b.id][b.flag];
    }
};
inline int read(){
    char ch=getchar();
    int f=1,x=0;
    while(!(ch>='0'&&ch<='9')){
        if(ch=='-')
            ch=-1;
        ch=getchar();
    }
    while(ch>='0'&&ch<='9')
        x=x*10+ch-'0',ch=getchar();
    return f*x;
}
void add(int x,int y,int z){
    to[cnt]=y;
    w[cnt]=z;
    nxt[cnt]=hd[x];
    hd[x]=cnt++;
}
void dijkstra(){
    priority_queue<lala> pq;
    dis[s][0]=0,num[s][0]=1,pq.push(lala(s,0));
    while(!pq.empty()){
        lala top=pq.top();  
        pq.pop();
        int u=top.id,flag=top.flag;
        if(vis[u][flag])
            continue;
        vis[u][flag]=true;
        for(int i=hd[u];i!=-1;i=nxt[i]){
            int v=to[i],lalala=dis[u][flag]+w[i];
            if(lalala<dis[v][0]){
                if(dis[v][0]!=inf)
                    dis[v][1]=dis[v][0],num[v][1]=num[v][0],pq.push(lala(v,1));
                dis[v][0]=lalala,num[v][0]=num[u][flag],pq.push(lala(v,0));  
            }
            else if(lalala==dis[v][0])
                num[v][0]+=num[u][flag];
            else if(lalala<dis[v][1])
                dis[v][1]=lalala,num[v][1]=num[u][flag],pq.push(lala(v,1)) ;
            else if(lalala==dis[v][1])      
                num[v][1]+=num[u][flag];
        }
    } 
}
signed main(void){
    cas=read();
    while(cas--){
        n=read(),m=read();
        memset(hd,-1,sizeof(hd)),cnt=0;
        memset(vis,false,sizeof(vis));
        memset(dis,inf,sizeof(dis));
        memset(num,0,sizeof(num));
        for(int i=1,x,y,z;i<=m;i++)
            x=read(),y=read(),z=read(),add(x,y,z);
        s=read(),e=read();
        dijkstra();
        int ans=num[e][0];
        if(dis[e][1]-1==dis[e][0])
            ans+=num[e][1];
        cout<<ans<<endl;
    }
    return 0;
}

by >o< neighthorn

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值