题目描述
题解
-
首先证明一个结论:公共部分一定是连续的一段
因为如果公共部分分成了两段,可以将中间部分强行拼成一段。即一个人可以走另一个人在断开部分的路线,这样一定可以时答案变优。因此,公共部分一定是连续的一段。 -
step2:我们可以预处理A到B的最短路图和C到D的最短路图。
具体的实现方法时建立正图和反图分别以这四个点跑Dijkstra,枚举每一条边(x,y,v)看看是否满足:dis1x+dis2y+v=dis1B/Ddis1_x+dis2_y+v=dis1_{B/D}dis1x+dis2y+v=dis1B/D -
step3:我们发现这张最短路图就是一张DAG,因此我们只需要进行一遍拓扑排序求出最短路图的最长链即可=为最终的答案。
#include <bits/stdc++.h>
using namespace std;
const int N = 100000;
vector < pair<int,int> > G1[N], G2[N];
int n, m, A, B, C, D, tot = 0;
int vis[5][N], dis[5][N], Link[N], rd[N], used[N], f[N];
struct node {
int y, next;
} e[N*2];
void Dijkstra(int num,vector< pair<int,int> >a[N],int st)
{
memset(vis[num],0,sizeof vis[num]);
memset(dis[num],30,sizeof dis[num]);
dis[num][st] = 0;
priority_queue< pair<int,int> > q;
q.push(make_pair(0,st));
while (q.size())
{
int x = q.top().second; q.pop();
if (vis[num][x]) continue; vis[num][x] = 1;
for (int i=0;i<a[x].size();++i)
{
int y = a[x][i].first;
int v = a[x][i].second;
if (dis[num][x] + v < dis[num][y]) {
dis[num][y] = dis[num][x] + v;
q.push(make_pair(-dis[num][y],y));
}
}
}
return;
}
void add(int x,int y)
{
e[++tot] = node{y,Link[x]};
Link[x] = tot, rd[y] ++;
}
int Topsort(void)
{
queue <int> q;
for (int i=1;i<=n;++i)
if (rd[i] == 0) q.push(i);
while (q.size())
{
int x = q.front(); q.pop();
for (int i=Link[x];i;i=e[i].next)
{
int y = e[i].y;
rd[y] --;
f[y] = max(f[x]+1,f[y]);
if (!rd[y]) q.push(y);
}
}
int ans = 0;
for (int i=1;i<=n;++i)
ans = max(ans,f[i]);
return ans;
}
int main(void)
{
freopen("game.in","r",stdin);
freopen("game.out","w",stdout);
scanf("%d %d", &n, &m);
for (int i=1;i<=m;++i)
{
int x, y, v;
scanf("%d %d %d", &x, &y, &v);
G1[x].push_back(make_pair(y,v));
G2[y].push_back(make_pair(x,v));
}
scanf("%d %d %d %d", &A, &B, &C, &D);
Dijkstra(1,G1,A);
Dijkstra(2,G1,C);
Dijkstra(3,G2,B);
Dijkstra(4,G2,D);
if (dis[1][B] == dis[1][0] || dis[2][D] == dis[2][0])
return puts("-1"), 0;
for (int x=1;x<=n;++x)
for (int i=0;i<G1[x].size();++i)
{
int y = G1[x][i].first;
int v = G1[x][i].second;
if (dis[1][x]+v+dis[3][y] == dis[1][B]
&& dis[2][x]+v+dis[4][y] == dis[2][D]) add(x,y);
}
cout<<1+Topsort()<<endl;
return 0;
}