[SDOI2009]Elaxia的路線 ---最短路 + 拓撲求最長路
阿新 • • 發佈:2019-01-29
題目描述
最近,和的關係特別好,他們很想整天在一起,但是大學的學習太緊張了,他們 必須合理地安排兩個人在一起的時間。
和每天都要奔波於宿舍和實驗室之間,他們 希望在節約時間的前提下,一起走的時間儘可能的長。
現在已知的是和所在的宿舍和實驗室的編號以及學校的地圖:地圖上有個路 口,條路,經過每條路都需要一定的時間。 具體地說,就是要求無向圖中,兩對點間最短路的最長公共路徑。
分析
首先明確一點,最短路的最長公共路徑一定是一條鏈。因此,可以考慮先求出公共的最短路徑,再通過拓撲dp求出最長的那一段(最長路)。
判斷方法:若在最短路徑上,則,由於是無向圖,所以直接以為起點跑一遍最短路即可
注意:對於一條無向邊(u,v),若存在與,也視為公共路徑。
程式碼
#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;
}