题意:一张无向图求出两个点对最短路上的最长链边权和。
题解:四次dij,源点分别为
s
1
,
t
1
,
s
2
,
t
2
s_1,t_1,s_2,t_2
s1,t1,s2,t2,然后可以用以下两个式子的逻辑与来判断
e
e
e这条边在不在两个点对的最短路同向的最长链。
(
u
=
e
.
f
r
o
m
,
v
=
e
.
t
o
,
w
=
e
.
d
i
s
t
)
(u=e.from,v=e.to,w=e.dist)
(u=e.from,v=e.to,w=e.dist)
d
[
0
]
[
u
]
+
w
+
d
[
1
]
[
v
]
=
=
d
[
0
]
[
t
1
]
d[0][u]+w+d[1][v]==d[0][t1]
d[0][u]+w+d[1][v]==d[0][t1]
d
[
2
]
[
u
]
+
w
+
d
[
3
]
[
v
]
=
=
d
[
2
]
[
t
2
]
d[2][u]+w+d[3][v]==d[2][t2]
d[2][u]+w+d[3][v]==d[2][t2]
如果在最长链上,就把
e
e
e加入一个新图中,显然,这个新图是一个
D
A
G
DAG
DAG。
然后对这个
D
A
G
DAG
DAG进行拓扑排序,在拓扑排序过程中就可以进行
d
p
dp
dp找出最长链的长度了。
然后再重新建图,用以下两个式子的逻辑与来判断
e
e
e这条边在不在两个点对的最短路反向的最长链。
(
u
=
e
.
f
r
o
m
,
v
=
e
.
t
o
,
w
=
e
.
d
i
s
t
)
(u=e.from,v=e.to,w=e.dist)
(u=e.from,v=e.to,w=e.dist)
d
[
0
]
[
u
]
+
w
+
d
[
1
]
[
v
]
=
=
d
[
0
]
[
t
1
]
d[0][u]+w+d[1][v]==d[0][t1]
d[0][u]+w+d[1][v]==d[0][t1]
d
[
3
]
[
u
]
+
w
+
d
[
2
]
[
v
]
=
=
d
[
2
]
[
t
2
]
d[3][u]+w+d[2][v]==d[2][t2]
d[3][u]+w+d[2][v]==d[2][t2]
如果在最长链上,就把
e
e
e加入一个新图中,显然,这个新图是一个
D
A
G
DAG
DAG。
然后对这个
D
A
G
DAG
DAG进行拓扑排序,在拓扑排序过程中就可以进行
d
p
dp
dp找出最长链的长度了。
#include<cstdio>
#include<cstring>
#include<queue>
#include<vector>
#include<algorithm>
using namespace std;
const int N = 1500 + 3;
const int INF = 0x3f3f3f3f;
struct Edge{
int from,to,dist;
Edge(int from,int to,int dist):from(from),to(to),dist(dist){}
};
struct HeapNode{
int d,u;
HeapNode(int d,int u):d(d),u(u){}
bool operator < (const HeapNode& rhs) const {
return d > rhs.d;
}
};
struct Dijkstra {
int n,m;
vector<Edge> edges;
vector<int> G[N];
bool done[N];
int d[4][N];
void init(int n) {
this->n = n;
for(int i=0;i<n;i++) G[i].clear();
edges.clear();
}
void AddEdge(int from,int to,int dist) {
edges.push_back(Edge(from,to,dist));
m = edges.size();
G[from].push_back(m-1);
}
void dijkstra(int s,int id) {
priority_queue<HeapNode> q;
for(int i=0;i<n;i++) d[id][i] = INF;
d[id][s] = 0;
memset(done,0,sizeof(done));
q.push(HeapNode(0,s));
while(!q.empty()) {
HeapNode x = q.top(); q.pop();
int u = x.u;
if(done[u]) continue;
done[u] = true;
for(int i=0;i<G[u].size();i++) {
Edge& e = edges[G[u][i]];
if(d[id][e.to] > d[id][u] + e.dist) {
d[id][e.to] = d[id][u] + e.dist;
q.push(HeapNode(d[id][e.to],e.to));
}
}
}
}
};
struct Toposort {
int n,m;
int du[N];
int len[N];
vector<int> G[N];
vector<Edge> edges;
queue<int> q;
inline void init(int n) {
this->n = n;
for(int i=0;i<n;i++) G[i].clear();
edges.clear();
}
inline void AddEdge(int u,int v,int w) {
edges.push_back(Edge(u,v,w));
m = edges.size();
G[u].push_back(m-1);
}
inline int topo() {
int ans = 0;
fill(du,du+n,0); fill(len,len+n,0);
for(int i=0;i<n;i++) for(int j=0;j<G[i].size();j++) du[edges[G[i][j]].to]++;
int tot = 0;
for(int i=0;i<n;i++) if(!du[i]) q.push(i);
while(!q.empty()) {
int x = q.front(); q.pop();
for(int j=0;j<G[x].size();j++) {
Edge &e = edges[G[x][j]]; int t = e.to;
du[t]--;
len[t] = max(len[t],len[e.from]+e.dist);
ans = max(ans,len[t]);
if(!du[t]) q.push(t);
}
}
return ans;
}
};
Dijkstra solver1;
Toposort solver2;
int main() {
int n,m; scanf("%d%d",&n,&m);
solver1.init(n);
int s1,t1,s2,t2; scanf("%d%d%d%d",&s1,&t1,&s2,&t2); s1--; t1--; s2--; t2--;
while(m--) {
int u,v,w; scanf("%d%d%d",&u,&v,&w); u--; v--;
solver1.AddEdge(u,v,w);
solver1.AddEdge(v,u,w);
}
solver1.dijkstra(s1,0);solver1.dijkstra(t1,1);
solver1.dijkstra(s2,2);solver1.dijkstra(t2,3);
solver2.init(n);
for(int i=0;i<solver1.edges.size();i++) {
Edge& e = solver1.edges[i];
int u = e.from,v = e.to,w = e.dist;
if(solver1.d[0][u]+w+solver1.d[1][v]==solver1.d[0][t1] && solver1.d[2][u]+w+solver1.d[3][v]==solver1.d[2][t2]) {
solver2.AddEdge(u,v,w);
}
}
int ans = solver2.topo();
solver2.init(n);
for(int i=0;i<solver1.edges.size();i++) {
Edge& e = solver1.edges[i];
int u = e.from,v = e.to,w = e.dist;
if(solver1.d[0][u]+w+solver1.d[1][v]==solver1.d[0][t1] && solver1.d[3][u]+w+solver1.d[2][v]==solver1.d[2][t2]) {
solver2.AddEdge(u,v,w);
}
}
ans = max(ans,solver2.topo());
printf("%d\n",ans);
return 0;
}