AOJ2010 Poor Mail Forwarding
問題リンク Poor Mail Forwarding
- 解法
シミュレーション問題です。
郵便局iから宛先jの手紙を出すときの転送先の郵便局は常に同じなので、前計算してしまいましょう。
e[i][j]でi->jの最短経路。ワーシャルフロイドで求めます。
adj[i][j]でi->jの直接転送経路。つまりは、入力の辺のことです。
ここで、郵便局iに宛先jの手紙が来たときのこの手紙の転送先は
e[i][j] == adj[i][k]+e[k][j]
を満たす最小のkです。
シミュレーション時に起きるイベントは
SEND: 郵便局に配達人が手紙を持って到着した
BACK: 郵便局に配達人が配達から帰ってきた
INFORM: 郵便局に手紙が届いた
となります。
SENDイベントが起きた時
送られた手紙の宛先と到着した郵便局が一致したらそれは解です。そうでなければ郵便局に手紙を蓄えます。
INFORMイベントが起きたとき
その時点で配達人が郵便局に居たら、即座に出発させます。居なかったとき、特に何もしません。
BACKイベントが起きたとき
郵便局に手紙がたまっていたら即座に出発させます。無かったら特に何もしません。
後はこれを根性で実装します。
- ソース
import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.LinkedList; import java.util.List; import java.util.PriorityQueue; import java.util.Scanner; //Poor Mail Forwarding public class AOJ2010 { final int SEND = 0, BACK = 1, INFORM = 2; int INF = 1<<29; int[][] e, next; boolean[] exist; int[] from, to; String[] letter; LinkedList<P>[] post; class T{ int from; List<Integer> list; public T(int from) { this.from = from; list = new ArrayList<Integer>(); } } class P implements Comparable<P>{ int at, id, t; public P(int at, int id, int t) { this.at = at; this.id = id; this.t = t; } public int compareTo(P o) { return t!=o.t?t-o.t:next[at][to[id]]-next[at][to[o.id]]; } } class E implements Comparable<E>{ int type, data, t; T con; public E(int type, int data, int t, T c) { this.type = type; this.data = data; this.t = t; con = c; } public int compareTo(E o) { return t!=o.t?t-o.t:type-o.type; } } class R implements Comparable<R>{ String s; int t; public R(String s, int t) { this.s = s; this.t = t; } public int compareTo(R o) { return t!=o.t?t-o.t:s.compareTo(o.s); } } @SuppressWarnings("unchecked") void run(){ Scanner sc = new Scanner(System.in); boolean head = true; for(;;){ int n = sc.nextInt(), m = sc.nextInt(); if((n|m)==0)break; if(!head)System.out.println(); head = false; e = new int[n][n]; int[][] adj = new int[n][n]; for(int[]a:e)Arrays.fill(a, INF); for(int[]a:adj)Arrays.fill(a, INF); while(m--!=0){ int s = sc.nextInt()-1, t = sc.nextInt()-1, d = sc.nextInt(); e[s][t] = e[t][s] = d; adj[s][t] = adj[t][s] = d; } for(int i=0;i<n;i++)e[i][i]=0; for(int k=0;k<n;k++)for(int i=0;i<n;i++)for(int j=0;j<n;j++)e[i][j]=Math.min(e[i][j], e[i][k]+e[k][j]); next = new int[n][n]; for(int i=0;i<n;i++)for(int j=0;j<n;j++){ if(i==j||e[i][j]==INF)continue; for(int k=0;k<n;k++){ if(i==k||adj[i][k]==INF)continue; if(e[i][j]==adj[i][k]+e[k][j]){ next[i][j] = k; break; } } } PriorityQueue<R> res = new PriorityQueue<R>(); exist = new boolean[n]; Arrays.fill(exist, true); PriorityQueue<E> q = new PriorityQueue<E>(); int L = sc.nextInt(); from = new int[L]; to = new int[L]; letter = new String[L]; post = new LinkedList[n]; for(int i=0;i<n;i++)post[i] = new LinkedList<P>(); for(int i=0;i<L;i++){ from[i] = sc.nextInt()-1; to[i] = sc.nextInt()-1; int time = sc.nextInt(); letter[i] = sc.next(); post[from[i]].add(new P(from[i], i, time)); q.add(new E(INFORM, from[i], time, null)); } while(!q.isEmpty()){ E event = q.poll(); int pos = event.data; if(event.type==BACK){ if(post[pos].isEmpty()){ exist[pos] = true; continue; } Collections.sort(post[pos]); if(event.t<post[pos].peek().t){ exist[pos] = true; continue; } exist[pos] = false; T t = new T(pos); P p = post[pos].remove(0); t.list.add(p.id); int nx = next[pos][to[p.id]]; for(int i=0;i<post[pos].size();i++){ P tmp = post[pos].get(i); if(event.t<tmp.t)break; if(nx==next[pos][to[tmp.id]]){ post[pos].remove(i); t.list.add(tmp.id); i--; } } int nt = event.t+e[pos][nx]; q.add(new E(SEND, nx, nt, t)); q.add(new E(INFORM, nx, nt, null)); } else if(event.type==INFORM){ if(!exist[pos])continue; if(post[pos].isEmpty())continue; Collections.sort(post[pos]); if(event.t<post[pos].peek().t)continue; exist[pos] = false; T t = new T(pos); P p = post[pos].remove(0); t.list.add(p.id); int nx = next[pos][to[p.id]]; for(int i=0;i<post[pos].size();i++){ P tmp = post[pos].get(i); if(event.t<tmp.t)break; if(nx==next[pos][to[tmp.id]]){ post[pos].remove(i); t.list.add(tmp.id); i--; } } int nt = event.t+e[pos][nx]; q.add(new E(SEND, nx, nt, t)); q.add(new E(INFORM, nx, nt, null)); } else if(event.type==SEND){ T t = event.con; q.add(new E(BACK, t.from, event.t+e[pos][t.from], null)); boolean offer = false; for(int id:t.list){ if(pos==to[id]){ res.add(new R(letter[id], event.t)); continue; } if(!offer)q.add(new E(INFORM, pos, event.t, null)); offer = true; post[pos].add(new P(pos, id, event.t)); } } } while(!res.isEmpty()){ R r = res.poll(); System.out.println(r.s+" "+r.t); } } } public static void main(String[] args) { new AOJ2010().run(); } }