Problem:
高速バス

A 君は高校の休みを利用して、高速バス(以下、「バス」 )で一人旅をする計画を立てています。まず、A 君は一番行ってみたい町を選んでそこを目的地にしました。次に出発地から目的地までバスを乗り継いでいくルートを決めなければなりません。乗り継ぎをするときは、バスを降りてから別のバスに乗り換えるので、それぞれのバスの乗車券が必要になります。

A 君は親戚のおじさんからバスの割引券を何枚かもらいました。 この券を 1 枚使うと乗車券 1 枚を半額で購入できます。例えば、図 1 の出発地5から目的地1へ行く場合には、5→4→6→2→1と5→3→1の二つの経路が考えられます。割引券が 2 枚あるとすると、交通費を最も安くするには5→4→6→2→1の経路をたどった場合、4→6と6→2の路線に割引を利用し、合計料金は 4600円となります。一方、5→3→1の経路をたどった場合、5→3と3→1の路線に割引を利用し、合計料金は 3750 円となります。

A 君は観光にお金を回したいので、交通費はできるだけ少なくしようと考えています。そこで A 君は、出発地から目的地までの最も安い交通費を求めるプログラムを作成することにしました。

図1

割引券の枚数、バスがつなぐ町の数、バスの路線数、各バスの路線情報を入力とし、出発地から目的地までの最も安い交通費を出力するプログラムを作成してください。各バスは双方向に同一料金で運行しています。また、町の数を n とすると、町にはそれぞれ異なる 1 から n までの番号が振られています。出発地から目的地までの経路は必ず存在するものとします。

Input

複数のデータセットの並びが入力として与えられます。 入力の終わりはゼロが５つの行で示されます。
各データセットは以下の形式で与えられます。

c n m s d
a1 b1 f1
a2 b2 f2
:
am bm fm

1 行目に割引券の枚数 c (1 ≤ c ≤ 10)、バスがつなぐ町の数 n (2 ≤ n ≤ 100)、バスの路線数 m (1 ≤ m ≤ 500)、出発地の町番号 s と目的地の町番号 d (s ≠ d) が与えられます。

続く m 行に第 i のバスの路線情報 ai, bi, fi (1 ≤ ai, bi ≤ n, 1000 ≤ fi ≤ 10000) が与えられます。ai, bi はバスの路線の始点と終点の町番号、fi はこの路線の料金を表す100 刻みの整数です。

データセットの数は 100 を超えません。

Output

入力データセットごとに、最も安い交通費を１行に出力します。

Sample Input

1 3 3 1 3
1 3 2000
1 2 1000
2 3 1000
2 3 3 1 3
1 3 2300
1 2 1000
2 3 1200
2 6 6 5 1
1 2 1500
1 3 4500
2 6 2000
5 4 1000
6 4 2200
3 5 3000
0 0 0 0 0

Output for the Sample Input

1000
1100
3750

Solution in C (judge verdict: Accepted)

#include <stdio.h>

#define TRUE        1
#define FALSE       0

#define CITY_MAX    101
#define CICKET_MAX  10
#define LINE_MAX    (501*2)

#define COST_MAX    10000000

#define QUE_SIZE    (LINE_MAX*CICKET_MAX)


int mincost[CITY_MAX][CICKET_MAX];
int gone[CITY_MAX][CICKET_MAX];

int first_line[CITY_MAX]; /* first index of a bus departing from the city */

int line_dst[LINE_MAX];  /* destination */
int line_cost[LINE_MAX]; /* cost */
int line_next[LINE_MAX]; /* next index of a bus departing from the same city */

/* priority queue */
typedef struct _QueItem {
    int cost;
    int city;
    int cicket;
} QueItem;
QueItem heapq[QUE_SIZE]; /* index 0: unuse, index 1.. : que */
int quecnt;

void enq(QueItem a);
QueItem deq();
int qcmp(QueItem a, QueItem b);


int main(){
    QueItem item,item2;
    int c,n,m,s,d;
    int a,b,f;
    int i,j;
    int ans;

    while(1){
        /* ram init */
        quecnt=0;
        for(i=0;i<CITY_MAX;i++){
            first_line[i]=-1;
            for(j=0;j<CICKET_MAX;j++){
                mincost[i][j]=COST_MAX;
                gone[i][j]=FALSE;
            }
        }

        /* input */
        scanf("%d %d %d %d %d",&c,&n,&m,&s,&d);
        if(c==0)break;

        for( i=0; i<m; i++ ){
            scanf("%d %d %d",&a,&b,&f);
            /* b -> a */
            line_dst[i*2] = a;
            line_cost[i*2] = f;
            line_next[i*2] = first_line[b];
            first_line[b] = i*2;
            /* a -> b */
            line_dst[i*2+1] = b;
            line_cost[i*2+1] = f;
            line_next[i*2+1] = first_line[a];
            first_line[a] = i*2+1;
        }

        /* dijkstra */
        item.cost=0;
        item.city=s;
        item.cicket=c;
        enq(item);
        while(quecnt>0){
            item = deq();
            if(gone[item.city][item.cicket])continue;
            gone[item.city][item.cicket] = TRUE;
            mincost[item.city][item.cicket] = item.cost;

            /* all bus line from item.city */
            i=first_line[item.city];
            while(i>=0){
                int dst = line_dst[i];
                int cost = line_cost[i];
                /* cicket nouse */
                if(gone[dst][item.cicket]==FALSE){
                    item2.cost=item.cost+cost;
                    item2.city=dst;
                    item2.cicket=item.cicket;
                    enq(item2);
                }
                /* cicket use */
                if(item.cicket>0 && gone[dst][item.cicket]==FALSE){
                    item2.cost=item.cost+cost/2;
                    item2.city=dst;
                    item2.cicket=item.cicket-1;
                    enq(item2);
                }
                i = line_next[i];
            }
        }

        ans=COST_MAX;
        for(i=0;i<c;i++){
            if(mincost[d][i]<ans)ans=mincost[d][i];
        }
        printf("%d\n",ans);
    }

    return 0;
}

/* add a to heapq */
void enq(QueItem a){
    int i;
    QueItem tmp;
    quecnt++;
    heapq[quecnt] = a;
    for(i=quecnt;i/2>0;i/=2){
        if(qcmp(heapq[i/2],heapq[i]))break;
        tmp = heapq[i];
        heapq[i] = heapq[i/2];
        heapq[i/2] = tmp;
    }
}

/* get highest priority item in heapq */
QueItem deq(){
    int i,target;
    QueItem tmp,ret;
    ret = heapq[1];
    heapq[1] = heapq[quecnt];
    quecnt--;
    for(i=1;i*2<=quecnt;){
        if( i*2+1<=quecnt && qcmp(heapq[i*2+1],heapq[i]) ){
            if( qcmp(heapq[i*2],heapq[i*2+1]) ){
                target = i*2;
            }else{
                target = i*2+1;
            }
        }else if( qcmp(heapq[i*2],heapq[i]) ){
            target = i*2;
        }else{
            break;
        }
        tmp = heapq[i];
        heapq[i] = heapq[target];
        heapq[target] = tmp;
        i = target;
    }
    return ret;
}

/* return TRUE if priority(a) > priority(b) */
int qcmp(QueItem a, QueItem b){
    return (a.cost<b.cost);
}