https://www.luogu.org/problemnew/show/P2149
最近,Elaxia和w的关系特别好,他们很想整天在一起,但是大学的学习太紧张了,他们 必须合理地安排两个人在一起的时间。
Elaxia和w每天都要奔波于宿舍和实验室之间,他们 希望在节约时间的前提下,一起走的时间尽可能的长。
现在已知的是Elaxia和w**所在的宿舍和实验室的编号以及学校的地图:地图上有N个路 口,M条路,经过每条路都需要一定的时间。 具体地说,就是要求无向图中,两对点间最短路的最长公共路径。
分析样例发现最长公共路径可以包括两个人不同方向同一条路即可。
从两个起点、终点跑四边spfa得到不同起点的dis数组用于判断某一边是否存在与最短路中,将x1->y1, x2->y2的最短路边加入到新的图中,在从新图中x1->y1拓扑排序,记录一个结果
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int, int> pa;
const int maxn = 1500 + 10;
const int INF = 0x3f3f3f3f;
struct node {
int to, val;
node(int _to, int _val) : to(_to), val(_val) {}
bool operator < (const node& x) const {
return val > x.val;
}
};
int dis[6][maxn], tot, tot_, head[maxn], head_[maxn], cnt[maxn], dp[maxn], vis[maxn];
struct edge {
int frm, to, val, nxt, im;
edge() {}
edge(int _frm, int _to, int _val, int _nxt) : frm(_frm), to(_to), val(_val), nxt(_nxt) {}
edge(int _frm, int _to, int _val, int _nxt, int _x) : frm(_frm), to(_to), val(_val), nxt(_nxt), im(_x) {}
} E[maxn * maxn], E_[maxn * maxn];
void addEdge(int u, int v, int w) {
E[++tot] = edge(u, v, w, head[u]);
head[u] = tot;
}
void addEdge_(int u, int v, int w, int x) {
E_[++tot_] = edge(u, v, w, head_[u], x);
head_[u] = tot_;
}
void spfa(int cnt, int s) {
priority_queue<node> q;
q.push(node(s, 0));
register int i;
memset(dis[cnt], 1, sizeof(dis[cnt]));
memset(vis, 0, sizeof(vis));
dis[cnt][s] = 0;
while(!q.empty()) {
node x = q.top();
q.pop();
vis[x.to] = 1;
for (i = head[x.to]; i; i = E[i].nxt) {
if(vis[E[i].to]) continue;
if(dis[cnt][E[i].to] > dis[cnt][x.to] + E[i].val) {
dis[cnt][E[i].to] = dis[cnt][x.to] + E[i].val;
q.push(node(E[i].to, dis[cnt][E[i].to]));
}
}
}
}
int main()
{
int n, m, x1, y1, x2, y2, u, v, w;
scanf("%d%d", &n, &m);
scanf("%d%d%d%d", &x1, &y1, &x2, &y2);
register int i;
for (i = 0; i < m; i++) {
scanf("%d%d%d", &u, &v, &w);
addEdge(u, v, w);
addEdge(v, u, w);
}
spfa(1, x1);
spfa(2, y1);
spfa(3, x2);
spfa(4, y2);
for (i = tot; i > 0; i--) {
u = E[i].frm, v = E[i].to, w = E[i].val;
if (dis[1][u] + w + dis[2][v] == dis[1][y1]) {
if(dis[3][u] + w + dis[4][v] == dis[3][y2] || dis[4][u] + w + dis[3][v] == dis[3][y2])
addEdge_(u, v, w, 1);
else
addEdge_(u, v, w, 0);
cnt[v]++; //入度
}
}
//topo
queue<int> q;
q.push(x1);
while(!q.empty()) {
int x = q.front();
q.pop();
for (i = head_[x]; i; i = E_[i].nxt) {
if(!(--cnt[E_[i].to]))
q.push(E_[i].to);
dp[E_[i].to] = max(dp[E_[i].to], dp[E_[i].frm] + E_[i].val * E_[i].im);
}
}
printf("%d\n", dp[y1]);
// system("pause");
}