SPOJ CANDN

Summary
Given a graph with 5000 vertices and three special vertices B, N, C.

Find a path from B to N (call it P1) and another path from B to C (call it P2), such that P1 and P2 are the shortest possible, and the total weight of the shared edges of P1 and P2 is maximum.

Explanation
Find a vertex V in the graph such that SP[B][V] + SP[V][N] == SP[B][N], and SP[B][V] + SP[V][C] == SP[B][C], and SP[B][V] is maximized.

SP[A][B] means the shortest path value from vertex A to vertex B.

Such a vertex V is guaranteed to be in one of P1 and one of P2 (proof it yourself).

To find such vertex V, we only need to know single source shortest paths from vertices B, N, C.

Therefore, three runs of Dijkstra (on B,N,C) and a brute force (to find V) is enough.

Implementations

 * 1) include 
 * 2) include
 * 3) include
 * 4) include

using namespace std;


 * 1) define REP(i,n) for (int i=0,_n=n; i<_n; i++)
 * 2) define MAXN 5010
 * 3) define INF 1000000000

vector > con[MAXN]; int J,B,C,N,S,Dc[MAXN],Dn[MAXN],Db[MAXN];

void dijkstra(int S, int D[]){ REP(i,J) D[i] = INF; D[S] = 0; priority_queue > pq; pq.push(make_pair(0,S)); while (pq.size){ pair p = pq.top; pq.pop; int d = -p.first, u = p.second; if (d > D[u]) continue; REP(i,con[u].size){ int v = con[u][i].first; int x = con[u][i].second; if (D[u] + x < D[v]){ D[v] = D[u] + x;               pq.push(make_pair(-D[v], v)); }       }    } }

int main{ while (scanf("%d %d %d %d %d",&J,&B,&C,&N,&S)!=EOF && J!=-1){ B--; C--; N--; REP(i,J) con[i].clear; REP(i,S){ int a, b, c;           scanf("%d %d %d",&a,&b,&c); a--; b--; con[a].push_back(make_pair(b,c)); con[b].push_back(make_pair(a,c)); }       dijkstra(B,Db); dijkstra(N,Dn); dijkstra(C,Dc); int T = 0; REP(i,J) if (Db[i]+Dn[i] == Dn[B]) if (Db[i]+Dc[i] == Dc[B]) T = max(T, Db[i]); printf("%d %d %d\n",T,Dc[B]-T,Dn[B]-T); } }