bzoj1880: [Sdoi2009]Elaxia的路線(spfa,拓撲排序最長路)
阿新 • • 發佈:2018-11-10
1880: [Sdoi2009]Elaxia的路線
Time Limit: 4 Sec Memory Limit: 64 MBSubmit: 1944 Solved: 759
[Submit][Status][Discuss]
Description
最近,Elaxia和w**的關係特別好,他們很想整天在一起,但是大學的學習太緊張了,他們 必須合理地安排兩個人在一起的時間。Elaxia和w**每天都要奔波於宿舍和實驗室之間,他們 希望在節約時間的前提下,一起走的時間儘可能的長。 現在已知的是Elaxia和w**所在的宿舍和實驗室的編號以及學校的地圖:地圖上有N個路 口,M條路,經過每條路都需要一定的時間。 具體地說,就是要求無向圖中,兩對點間最短路的最長公共路徑。Input
第一行:兩個整數N和M(含義如題目描述)。 第二行:四個整數x1、y1、x2、y2(1 ≤ x1 ≤ N,1 ≤ y1 ≤ N,1 ≤ x2 ≤ N,1 ≤ ≤ N),分別表示Elaxia的宿舍和實驗室及w**的宿舍和實驗室的標號(兩對點分別 x1,y1和x2,y2)。 接下來M行:每行三個整數,u、v、l(1 ≤ u ≤ N,1 ≤ v ≤ N,1 ≤ l ≤ 10000),表 u和v之間有一條路,經過這條路所需要的時間為l。 出出出格格格式式式::: 一行,一個整數,表示每天兩人在一起的時間(即最長公共路徑的長度)。Output
一行,一個整數,表示每天兩人在一起的時間(即最長公共路徑的長度)Sample Input
9 101 6 7 8
1 2 1
2 5 2
2 3 3
3 4 2
3 9 5
4 5 3
4 6 4
4 7 2
5 8 1
7 9 1
Sample Output
3HINT
對於30%的資料,N ≤ 100;
對於60%的資料,N ≤ 1000;
對於100%的資料,N ≤ 1500,輸入資料保證沒有重邊和自環。
Source
/*
如何求兩對點最短路的最長公共路徑?
開始的想法是對兩個起點spfa,但對於如何求多條最短路經過的所有點沒有思路
注意到其實本質是求最長路,只是需要一個圖......
正解是4遍spfa,若某條邊滿足起點和終點分別到這條邊最短路+這條路長等於起點到終點的最短路
那麼這條邊一定在最短路上。
所以就可以把1,2最短路徑都經過的邊重建圖(注意若某條邊不是被同向經過也要算)
這就有圖了...求最長路即可(顯然圖是DAG 拓撲排序可以求)。
*/
#include<bits/stdc++.h>
#define N 2005
#define M 1000007
#define inf 0x3f3f3f3f
using namespace std;
struct node{
int u,v,w,nxt,f;
}e[M<<1],E[M<<1];
queue<int>q;
int n,m,cnt,cnt2;
int head[N],p[5],d[5][N],Head[N];
int in[N],f[N],v[N];
void add(int u,int v,int w)
{
e[++cnt].u=u;e[cnt].v=v;e[cnt].w=w;
e[cnt].nxt=head[u]; head[u]=cnt;
}
void add_(int u,int v,int w)
{
E[++cnt2].u=u;E[cnt2].v=v;E[cnt2].w=w;
E[cnt2].nxt=Head[u]; Head[u]=cnt2;
}
void spfa(int x)
{
memset(v,0,sizeof v);
for(int i=1;i<=n;++i) if(i!=p[x]) d[x][i]=inf;
q.push(p[x]);v[p[x]]=1;
while(!q.empty())
{
int now=q.front();q.pop();v[now]=0;
for(int i=head[now];i;i=e[i].nxt)
{
int to=e[i].v;
if(d[x][to]>d[x][now]+e[i].w)
{
d[x][to]=d[x][now]+e[i].w;
if(!v[to]) v[to]=1,q.push(to);
}
}
}
}
void rebuild()
{
for(int i=1;i<=cnt;++i)
if(d[1][e[i].u]+e[i].w+d[2][e[i].v]==d[1][p[2]])
{
add_(e[i].u,e[i].v,e[i].w);
if(d[3][e[i].u]+e[i].w+d[4][e[i].v]==d[3][p[4]] || d[4][e[i].u]+e[i].w+d[3][e[i].v]==d[3][p[4]])
E[cnt2].f=1;
in[e[i].v]++;
}
}
void Tsort()
{
while(!q.empty()) q.pop();
q.push(p[1]);
int now;
while(!q.empty())
{
now=q.front(); q.pop();
for(int i=Head[now];i;i=E[i].nxt)
{
--in[E[i].v];
if(!in[E[i].v])
{
q.push(E[i].v);
f[E[i].v]=max(f[E[i].v],f[now]+E[i].w*E[i].f);
}
}
}
}
int main()
{
int x,y,z;
scanf("%d%d",&n,&m);
for(int i=1;i<=4;++i) scanf("%d",&p[i]);
for(int i=1;i<=m;++i)
{
scanf("%d%d%d",&x,&y,&z);
add(x,y,z),add(y,x,z);
}
for(int i=1;i<=4;++i) spfa(i);
rebuild();
Tsort();
printf("%d",f[p[2]]);
return 0;
}