1. 程式人生 > >bzoj1880: [Sdoi2009]Elaxia的路線(spfa,拓撲排序最長路)

bzoj1880: [Sdoi2009]Elaxia的路線(spfa,拓撲排序最長路)

1880: [Sdoi2009]Elaxia的路線

Time Limit: 4 Sec  Memory Limit: 64 MB
Submit: 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 10
1 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

3

HINT

對於30%的資料,N ≤ 100;
對於60%的資料,N ≤ 1000;
對於100%的資料,N ≤ 1500,輸入資料保證沒有重邊和自環。

Source

Day2

 

 

/*
如何求兩對點最短路的最長公共路徑?
開始的想法是對兩個起點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; }