dijkstra 堆优化!

2 篇文章 0 订阅

心态崩了!!

改了一天!发现是标记蓝白点的问题!每次从堆顶取出蓝点,去更新其它点要判断是不是白点!不然疯狂乱改!!


#include<iostream>
#include<cstdio>
using namespace std;

const int M = 1000005;
const int N = 100005;

int len, n, m, s; 
int diss[N];

int stot, tov[M], w[M], h[N], nex[M];
void add ( int u, int v, int s ) {
    tov[++stot] = v;
    w[stot] = s;
    nex[stot] = h[u];
    h[u] = stot;
}

struct node {
    int dis;
    int id;
} a[N];

int flag[N];

void shift_up ( int u ) {
    if ( u / 2 == 0 ) return ;
    int v = u / 2;
    if ( a[v].dis <= a[u].dis ) return ;
    swap ( a[v], a[u] );
    shift_up ( v );
}

void shift_down ( int u ) {
    if ( u * 2 > len ) return ;
    int v = u * 2;
    if ( v < len && a[v].dis > a[v+1].dis ) v++ ;
    if( a[v].dis >= a[u].dis ) return;
    swap ( a[u], a[v] );
    shift_down ( v );
}

void dijistra ( ) {
    for ( int i = 1; i <= n; i ++ )
        diss[i] = 2147483647;
    diss[s] = 0; a[1].dis = 0; a[1].id = s; len = 1;
    while ( len != 0 ) {
        int u = a[1].id;
        swap ( a[1], a[len] );
        len --;
        shift_down ( 1 );
        if ( flag[u] ) continue;
        flag[u] = 1;
        for ( int j = h[u]; j; j = nex[j] )
            if ( !flag[tov[j]] && diss[tov[j]] > diss[u] + w[j] ) {///有点悲伤了
                diss[tov[j]] = diss[u] + w[j];
                node v; v.dis = diss[tov[j]]; v.id = tov[j];
                a[++len] = v;
                shift_up ( len );
            }
    }
}

int read()
{   
    int ans=0;
    char x=getchar();
    while(x<'0'||x>'9') x=getchar();
    while(x>='0'&&x<='9')
    {
        ans=ans*10+x-'0';
        x=getchar();
    }
    return ans;
}

int main ( ) {
    scanf ( "%d%d%d", &n, &m, &s );
    for ( int i = 1; i <= m; i ++ ) {
        int u, v, sa;
        u = read ( ); v = read ( ); sa = read ( );
        add ( u, v, sa );
    }

    dijistra ( );
    for ( int i = 1; i <= n; i ++ )
        printf ( "%d ", diss[i] );
    return 0;
}

要去东北集训了,水篇博客让我不要被大佬们暴揍qwq%%%

继续努力。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值