1. 程式人生 > >[SDOI2009]Elaxia的路線 ---最短路 + 拓撲求最長路

[SDOI2009]Elaxia的路線 ---最短路 + 拓撲求最長路

題目描述

最近,ElaxiaElaxiaww**的關係特別好,他們很想整天在一起,但是大學的學習太緊張了,他們 必須合理地安排兩個人在一起的時間。

ElaxiaElaxiaww**每天都要奔波於宿舍和實驗室之間,他們 希望在節約時間的前提下,一起走的時間儘可能的長。

現在已知的是ElaxiaElaxiaww**所在的宿舍和實驗室的編號以及學校的地圖:地圖上有NN個路 口,MM條路,經過每條路都需要一定的時間。 具體地說,就是要求無向圖中,兩對點間最短路的最長公共路徑

分析

首先明確一點,最短路的最長公共路徑一定是一條鏈。因此,可以考慮先求出公共的最短路徑,再通過拓撲dp求出最長的那一段(最長路)。
判斷方法:若(

u,v,w)(u,v,w)x1y1x1 \to y1最短路徑上,則dis[x1][u]+w+dis[v][y1]==dis[x1][y1]dis[x1][u] + w + dis[v][y1] == dis[x1][y1],由於是無向圖,所以直接以x1,y1,x2,y2x1,y1,x2,y2為起點跑一遍最短路即可
注意:對於一條無向邊(u,v),若存在x1uvy1x1 \to u \to v \to y1x2vuy2x2 \to v \to u \to y2
,也視為公共路徑。

程式碼

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <vector>
#include <queue>

#define IL inline

using namespace std;

IL int read()
{
    char c = getchar();
    int sum = 0 ,k = 1;
    for(;'0' > c || c > '9'; c = getchar())
        if
(c == '-') k = -1; for(;'0' <= c && c <= '9'; c = getchar()) sum = sum * 10 + c - '0'; return sum * k; } int n, m; int to[2248505], nxt[2248505], val[2248505]; int cnt, last[1505]; IL void add(int u, int v, int w) { to[++cnt] = v; nxt[cnt] = last[u]; val[cnt] = w; last[u] = cnt; to[++cnt] = u; nxt[cnt] = last[v]; val[cnt] = w; last[v] = cnt; } typedef pair<int, int> pr; #define m_p(a, b) make_pair((a), (b)) int dis[4][1505]; priority_queue< pr, vector<pr>, greater<pr> >Q; IL void dijkstra(int u, int *d) { d[u] = 0; Q.push(m_p(0, u)); for(pr tmp; !Q.empty();) { tmp = Q.top(); Q.pop(); if(tmp.first != d[(u = tmp.second)]) continue; for(int i = last[u], v; (v = to[i]); i = nxt[i]) if(d[v] > d[u] + val[i]) { d[v] = d[u] + val[i]; Q.push(m_p(d[v], v)); } } } vector<int>mp[1505]; int size[1505]; int degree[1505]; queue<int>Q2; int f[1505]; int ans; IL int max_(int x, int y) { return x > y ? x : y; } IL void topsort() { for(int i = 1; i <= n; ++i) if(!degree[i] && size[i]) Q2.push(i); for(int u, v; !Q2.empty();) { u = Q2.front(); Q2.pop(); if(f[u] > ans) ans = f[u]; for(int i = 0; i < size[u]; ++i) { v = to[mp[u][i]]; f[v] = max_(f[u] + val[mp[u][i]], f[v]); if(!(--degree[v])) Q2.push(v); } } } int main() { n = read(); m = read(); int x1 = read(), y1 = read(), x2 = read(), y2 = read(); for(int i = 1, x, y; i <= m; ++i) { x = read(); y = read(); add(x, y, read()); } memset(dis, 0x3f, sizeof(dis)); dijkstra(x1, dis[0]); dijkstra(y1, dis[1]); dijkstra(x2, dis[2]); dijkstra(y2, dis[3]); for(int u = 1; u <= n; ++u) for(int i = last[u], v; (v = to[i]); i = nxt[i]) if(dis[0][u] + val[i] + dis[1][v] == dis[0][y1] && ( dis[2][u] + val[i] + dis[3][v] == dis[2][y2] || dis[2][v] + val[i] + dis[3][u] == dis[2][y2])) { //printf("%d %d %d\n", u, v, val[i]); mp[u].push_back(i); ++size[u]; ++degree[v]; } topsort(); printf("%d\n", ans); return 0; }