映射二叉堆+Dijkstra

幽幽子

#include <cstdio>
#include <cstring>
#define N 100010
#define M 400010
#define INF 999999999
int n,m,s,a,b;
int head[N],cnt;
struct Edge
{
    int v,next,w;
}edge[M];
struct Heap
{
    int d,v,p;
}heap[N];
int hl,pos[N];
void addedge(int u,int v,int w)
{
    edge[cnt].next=head[u]; edge[cnt].v=v; edge[cnt].w=w;
    head[u]=cnt++;
}
void swap(int a,int b)
{
    heap[0]=heap[a];    heap[a]=heap[b];    heap[b]=heap[0];
    pos[heap[a].v]=a;    pos[heap[b].v]=b;
}
void heapfy()
{
    int i=2;
    while (i<=hl)
    {
        if(i+1<=hl && heap[i+1].d<heap[i].d)i++;
        if(heap[i].d<heap[i>>1].d)
        {
            swap(i,i>>1);
            i<<=1;;
        }
        else break;
    }
}
void decrease(int i)
{
    while (i!=1 && heap[i].d<heap[i>>1].d)
    {
        swap(i,i>>1); i>>=1;
    }
}
void relax(int u,int v,int w)
{
    if(heap[pos[u]].d+w<heap[pos[v]].d)
    {
        heap[pos[v]].d=heap[pos[u]].d+w;
        decrease(pos[v]);
    }
}
void dijkstra(int s,int n)
{
    int u,i;
    for(i=1;i<=n;i++)
    {
        heap[i].v=pos[i]=i;    heap[i].d=INF;
    }
    heap[s].p=s;    heap[s].d=0;    swap(1,s);    hl=n;
    while (hl)
    {
        u=heap[1].v;
        swap(1,hl);
        hl--;
        heapfy();
        for(i=head[u];i!=-1;i=edge[i].next)
            if(pos[edge[i].v]<=hl) relax(u,edge[i].v,edge[i].w);
    }
}
int main ()
{
    int ds1,ds2,dab;
    while (scanf("%d%d%d%d%d",&m,&n,&s,&a,&b)!=-1)
    {
        cnt=0;
        memset(head,-1,sizeof(head));
        while (m--)
        {
            int u,v,w;
            scanf("%d%d%d",&u,&v,&w);
            addedge(u,v,w);
            addedge(v,u,w);
        }
        dijkstra(s,n);
        ds1=heap[pos[a]].d;
        ds2=heap[pos[b]].d;
        dijkstra(a,n);
        dab=heap[pos[b]].d;
        printf("%d\n",dab+(ds1<ds2?ds1:ds2));
    }
    
    return 0;
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值