Problem:
JOI 国の買い物事情(Shopping in JOI Kingdom)

JOI 国にはN 個の町があり，それらの間はM 本の双方向に通行可能な道路で結ばれている．K 個の町にはショッピングモールがあり，国民は道路を通ってそれらの町のいずれかに行き買い物をする．

家の場所によっては，買い物に行くために長い距離を移動する必要があり，それは非常に不便である．国王はこの実情を把握するため，ショッピングモールのある町までの最短距離が家の場所によってどれだけ長くなりうるのかを調べることにした．家は道路の途中に建てられることもあるので(入力例1 の説明を参照)，この調査は非常に大変である．そこで国王は，優秀なプログラマーであるあなたに，調査を行うプログラムの作成を依頼した．

課題

道路の情報とショッピングモールのある町の情報が与えられるとき，ショッピングモールのある町からもっとも遠い道路上の点(端点も含む) までの距離を求めるプログラムを作成せよ．町の中を移動するのにかかる距離は無視してよい．

制限

2 ≤ N ≤ 3000     JOI 国の町の個数

1 ≤ M ≤ 100000 = 105     JOI 国の道路の本数

1 ≤ K ≤ N     ショッピングモールがある町の個数

1 ≤ li ≤ 1000     i 番目の道路の長さ

入力

標準入力から以下の入力を読み込め．

1 行目には整数N, M, K が空白区切りで書かれている．N はJOI 国の町の個数を，M はJOI 国の道路の本数を，i>K はショッピングモールがある町の個数をそれぞれ表す．町には1, 2, ..., N の番号がつけられている．

続くM 行は道路の情報を表す．i + 1 行目(1 ≤ i ≤ M) には整数ai, bi, li (1 ≤ ai ≤ N, 1 ≤ bi ≤ N, 1 ≤ li ≤ 1000) が空白区切りで書かれている．これは，i 本目の道路が町ai と町bi を結んでおり，長さがli であることを表す．道路の両端が同じ町であることはない．また，任意の2 つの町p, q に対し，pとq を結ぶ道路は2 本以上存在しない．どの町からどの町へもいくつかの道路をたどって行くことができる．

続くK 行はショッピングモールの情報を表す．i+M+1 行目(1 ≤ i ≤ K) には1 つの整数si (1 ≤ si ≤ N)が書かれている．これは町si にショッピングモールがあることを表す．s1, ..., sK の中に同じ値が2
回以上現れることはない．

出力

標準出力に，ショッピングモールのある町までの最短距離の最大値の小数点以下を四捨五入した整数1
つを出力せよ．

採点基準

採点用データのうち，配点の40% 分については，K = 1 を満たす．

入出力の例

入力例1

3 3 1
1 2 1
2 3 1
3 1 1
1

出力例1

2

入力例1 は次のような町を表す．道路の長さはすべて1 である．ショッピングモールは町1 にしかない．

ショッピングモールのある町までもっとも遠い点は，町2 と町3 を結ぶ道路上の，町2 から距離0.5 の位置にある点であり，ショッピングモールのある町までの距離は1.5 である．よって，それを四捨五入した値である2 を出力する．

入力例2

4 5 2
1 2 4
1 3 1
2 3 2
2 4 2
3 4 1
2
4

出力例2

3

問題文と自動審判に使われるデータは、情報オリンピック日本委員会が作成し公開している問題文と採点用テストデータです。

Solution in C# (judge verdict: Accepted)

using System;
using System.Collections.Generic;
using System.Linq;
using Solver.Ex;
using Debug = System.Diagnostics.Debug;
using Watch = System.Diagnostics.Stopwatch;
using StringBuilder = System.Text.StringBuilder;
//using System.Numerics;
namespace Solver
{
    struct Edge
    {
        public int from, to, cost;
        public Edge(int f, int t, int c) : this() { from = f; to = t; cost = c; }
    }
    public class Solver
    {

        public void Solve()
        {
            var n = sc.Integer();
            var m = sc.Integer();
            var k = sc.Integer();
            var G = Enumerate(n, x => new List<KeyValuePair<int, int>>());
            var E = new Edge[m];
            for (int i = 0; i < m; i++)
            {
                var a = sc.Integer() - 1;
                var b = sc.Integer() - 1;
                var c = sc.Integer();
                G[a].Add(new KeyValuePair<int, int>(b, c));
                G[b].Add(new KeyValuePair<int, int>(a, c));
                E[i] = new Edge(a, b, c);
            }
            var shop = new bool[n];
            for (int i = 0; i < k; i++)
            {
                var a = sc.Integer() - 1;
                shop[a] = true;
            }
            var dist=new int[n];
            for (int i = 0; i < n; i++)
                dist[i] = 1 << 30;
            for (int v = 0; v < n; v++)
            {
                if (!shop[v]) continue;
                dist[v] = 0;
                var pq = new MergeablePriorityQueue<KeyValuePair<int, int>>((l,r)=>l.Value.CompareTo(r.Value));
                pq.Enqueue(new KeyValuePair<int, int>(v, 0));
                while(pq.Any())
                {
                    var p = pq.Dequeue();
                    if (dist[p.Key] < p.Value) continue;
                    foreach(var next in G[p.Key])
                        if(next.Value+p.Value<dist[next.Key])
                        {
                            dist[next.Key] = next.Value + p.Value;
                            pq.Enqueue(new KeyValuePair<int, int>(next.Key, dist[next.Key]));
                        }

                }
            }
            var ret = 0;
            foreach(var e in E)
            {
                var da = dist[e.from];
                var db = dist[e.to];
                var l = e.cost;
                if (da > db) { var tmp = da; da = db; db = tmp; }
                if (db - da > l) ret = Math.Max(db, ret);
                else ret = Math.Max(ret, (db + da + l) / 2 + (db + da + l) %2);             
            }
            IO.Printer.Out.WriteLine(ret);
           
        }


        internal IO.StreamScanner sc;
        static T[] Enumerate<T>(int n, Func<int, T> f) { var a = new T[n]; for (int i = 0; i < n; i++) a[i] = f(i); return a; }
    }

    #region Main and Settings
    static class Program
    {
        static void Main(string[] arg)
        {
#if DEBUG
            var errStream = new System.IO.FileStream(@"..\..\dbg.out", System.IO.FileMode.Create, System.IO.FileAccess.Write, System.IO.FileShare.ReadWrite);
            Debug.Listeners.Add(new System.Diagnostics.TextWriterTraceListener(errStream, "debugStream"));
            Debug.AutoFlush = false;
            var sw = new Watch(); sw.Start();
            IO.Printer.Out.AutoFlush = true;
            try
            {
#endif

                var solver = new Solver();
                solver.sc = new IO.StreamScanner(Console.OpenStandardInput());
                solver.Solve();
                IO.Printer.Out.Flush();
#if DEBUG
            }
            catch (Exception ex)
            {
                Console.Error.WriteLine(ex.Message);
                Console.Error.WriteLine(ex.StackTrace);
            }
            finally
            {
                sw.Stop();
                Console.ForegroundColor = ConsoleColor.Green;
                Console.Error.WriteLine("Time:{0}ms", sw.ElapsedMilliseconds);
                Debug.Close();
                System.Threading.Thread.Sleep(System.Threading.Timeout.Infinite);
            }
#endif
        }


    }
    #endregion
}

#region IO Helper
namespace Solver.IO
{
    public class Printer : System.IO.StreamWriter
    {
        static Printer()
        {
            Out = new Printer(Console.OpenStandardOutput()) { AutoFlush = false };
#if DEBUG
            Error = new Printer(Console.OpenStandardError()) { AutoFlush = true };
#else
            Error = new Printer(System.IO.Stream.Null) { AutoFlush = false };
#endif
        }
        public static Printer Out { get; set; }
        public static Printer Error { get; set; }
        public override IFormatProvider FormatProvider { get { return System.Globalization.CultureInfo.InvariantCulture; } }
        public Printer(System.IO.Stream stream) : base(stream, new System.Text.UTF8Encoding(false, true)) { }
        public Printer(System.IO.Stream stream, System.Text.Encoding encoding) : base(stream, encoding) { }
        public void Write<T>(string format, IEnumerable<T> source) { Write(format, source.OfType<object>().ToArray()); }
        public void WriteLine<T>(string format, IEnumerable<T> source) { WriteLine(format, source.OfType<object>().ToArray()); }
    }
    public class StreamScanner
    {
        public StreamScanner(System.IO.Stream stream) { iStream = stream; }
        private readonly System.IO.Stream iStream;
        private readonly byte[] buf = new byte[1024];
        private int len, ptr;
        private bool eof = false;
        public bool IsEndOfStream { get { return eof; } }
        const byte lb = 33, ub = 126, el = 10, cr = 13;
        public byte read()
        {
            if (eof) throw new System.IO.EndOfStreamException();
            if (ptr >= len) { ptr = 0; if ((len = iStream.Read(buf, 0, 1024)) <= 0) { eof = true; return 0; } }
            return buf[ptr++];
        }
        public char Char() { byte b = 0; do b = read(); while (b < lb || ub < b);            return (char)b; }
        public char[] Char(int n) { var a = new char[n]; for (int i = 0; i < n; i++) a[i] = Char(); return a; }
        public char[][] Char(int n, int m) { var a = new char[n][]; for (int i = 0; i < n; i++) a[i] = Char(m); return a; }
        public string Scan()
        {
            if (eof) throw new System.IO.EndOfStreamException();
            StringBuilder sb = null;
            var enc = System.Text.UTF8Encoding.Default;
            do
            {
                for (; ptr < len && (buf[ptr] < lb || ub < buf[ptr]); ptr++) ;
                if (ptr < len) break;
                ptr = 0;
                if ((len = iStream.Read(buf, 0, 1024)) <= 0) { eof = true; return ""; }
            } while (true);
            do
            {
                var f = ptr;
                for (; ptr < len; ptr++)
                    if (buf[ptr] < lb || ub < buf[ptr])
                    //if (buf[ptr] == cr || buf[ptr] == el)
                    {
                        string s;
                        if (sb == null) s = enc.GetString(buf, f, ptr - f);
                        else { sb.Append(enc.GetChars(buf, f, ptr - f)); s = sb.ToString(); }
                        ptr++; return s;
                    }
                if (sb == null) sb = new StringBuilder(enc.GetString(buf, f, len - f));
                else sb.Append(enc.GetChars(buf, f, len - f));
                ptr = 0;

            }
            while (!eof && (len = iStream.Read(buf, 0, 1024)) > 0);
            eof = true; return (sb != null) ? sb.ToString() : "";
        }
        public long Long()
        {
            long ret = 0; byte b = 0; bool isMynus = false;
            const byte zr = 48, nn = 57, my = 45;
            do b = read();
            while (b != my && (b < zr || nn < b));
            if (b == my) { isMynus = true; b = read(); }
            for (; true; b = read())
                if (b < zr || nn < b)
                    return isMynus ? -ret : ret;
                else ret = ret * 10 + b - zr;
        }
        public int Integer()
        {
            int ret = 0; byte b = 0; bool isMynus = false;
            const byte zr = 48, nn = 57, my = 45;
            do b = read();
            while (b != my && (b < zr || nn < b));
            if (b == my) { isMynus = true; b = read(); }
            for (; true; b = read())
                if (b < zr || nn < b)
                    return isMynus ? -ret : ret;
                else ret = ret * 10 + b - zr;
        }
        public double Double() { return double.Parse(Scan(), System.Globalization.CultureInfo.InvariantCulture); }
        public string[] Scan(int n) { var a = new string[n]; for (int i = 0; i < n; i++) a[i] = Scan(); return a; }
        public double[] Double(int n) { var a = new double[n]; for (int i = 0; i < n; i++) a[i] = Double(); return a; }
        public int[] Integer(int n) { var a = new int[n]; for (int i = 0; i < n; i++) a[i] = Integer(); return a; }
        public long[] Long(int n) { var a = new long[n]; for (int i = 0; i < n; i++)a[i] = Long(); return a; }
        public void Flush() { iStream.Flush(); }
    }
}
#endregion
#region Extension
namespace Solver.Ex
{
    static public partial class EnumerableEx
    {
        static public string AsString(this IEnumerable<char> ie) { return new string(ie.ToArray()); }
        //static public string AsJoinedString<T>(this IEnumerable<T> ie, string st = " ") { return string.Join(st, ie); }
    }
}
#endregion
#region PriorityQueue and PairingHeap
public class MergeablePriorityQueue<T>
{
    PairingHeap<T> top;
    Comparison<T> compare;
    int size;
    public int Count { get { return size; } }
    public MergeablePriorityQueue() : this(Comparer<T>.Default) { }
    public MergeablePriorityQueue(Comparison<T> comparison) { compare = comparison; }
    public MergeablePriorityQueue(IComparer<T> comparer) { compare = comparer.Compare; }
    public void Enqueue(T item)
    {
        var heap = new PairingHeap<T>(item);
        top = PairingHeap<T>.Merge(top, heap, compare);
        size++;
    }
    public T Dequeue()
    {
        var ret = top.Key;
        size--;
        top = PairingHeap<T>.Pop(top, compare);
        return ret;
    }
    public bool Any() { return size > 0; }
    public T Peek() { return top.Key; }
}

#region PairingHeap
public class PairingHeap<T>
{
    public PairingHeap(T k) { key = k; }
    private readonly T key;
    public T Key { get { return key; } }
    private PairingHeap<T> head;
    private PairingHeap<T> next;
    static public PairingHeap<T> Pop(PairingHeap<T> s, Comparison<T> compare)
    {
        return MergeLst(s.head, compare);
    }
    static public PairingHeap<T> Merge(PairingHeap<T> l, PairingHeap<T> r, Comparison<T> compare)
    {
        if (l == null || r == null) return l == null ? r : l;
        if (compare(l.key, r.key) > 0) Swap(ref l, ref r);
        r.next = l.head;
        l.head = r;
        return l;
    }
    static public PairingHeap<T> MergeLst(PairingHeap<T> s, Comparison<T> compare)
    {
        var n = new PairingHeap<T>(default(T));
        while (s != null)
        {
            PairingHeap<T> a = s, b = null;
            s = s.next; a.next = null;
            if (s != null) { b = s; s = s.next; b.next = null; }
            a = Merge(a, b, compare); a.next = n.next;
            n.next = a;
        }
        while (n.next != null)
        {
            var j = n.next;
            n.next = n.next.next;
            s = Merge(j, s, compare);
        }
        return s;
    }
    static void Swap(ref PairingHeap<T> l, ref PairingHeap<T> r) { var t = l; l = r; r = t; }
}
#endregion
#endregion