[Sdoi2009]Elaxia的路线

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,输入数据保证没有重边和自环。

分别以x1,y1,x2,y2为起点,做4次SPFA

分别算出dist[1~4][x]

那么我们可以找到他们各自最短路中相同的边

只要同时满足:

dist[1][u]+w(u,v)+dist[2][v]=dist[1][y1]

dist[3][u]+w(u,v)+dist[4][v]=dist[3][y2]

那么就说明,这条边同时处于两人的最短路上

然后将这些边建一个新图,可以保证无环

最后拓扑排序求出最长的链

但是,这道题隐藏了一个情况:

从y2~x2的w**与从x1~y1的Elaxia在边上相遇,也就是相向而行走一条边,也算共同走了这一条

也就是说,我们要将w**起点终点反转,重新建边和拓扑

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<algorithm>
  4 #include<cstring>
  5 #include<queue>
  6 using namespace std;
  7 struct Node
  8 {
  9   int next,to,dis;
 10 }edge[2000001],edge2[2000001];
 11 int head[2001],num,head2[2001],num2,dist[5][2001],f[2001],n,d[2001],ans,m;
 12 int s1,s2,t1,t2;
 13 bool vis[2001];
 14 void add(int u,int v,int w)
 15 {
 16   num++;
 17   edge[num].next=head[u];
 18   head[u]=num;
 19   edge[num].to=v;
 20   edge[num].dis=w;
 21 }
 22 void add_Top(int u,int v,int w)
 23 {
 24   num2++;
 25   edge2[num2].next=head2[u];
 26   head2[u]=num2;
 27   edge2[num2].to=v;
 28   edge2[num2].dis=w;
 29 }
 30 void SPFA(int S,int T,int p)
 31 {int i;
 32   queue<int>Q;
 33   memset(dist[p],127/3,sizeof(dist[p]));
 34   dist[p][S]=0;
 35   Q.push(S);
 36   while (Q.empty()==0)
 37     {
 38       int u=Q.front();
 39       Q.pop();
 40       vis[u]=0;
 41       for (i=head[u];i;i=edge[i].next)
 42     {
 43       int v=edge[i].to;
 44       if (dist[p][v]>dist[p][u]+edge[i].dis)
 45         {
 46           dist[p][v]=dist[p][u]+edge[i].dis;
 47           if (vis[v]==0)
 48         {vis[v]=1;
 49           Q.push(v);
 50         }
 51         }
 52     }
 53     }
 54 }
 55 void Top_sort()
 56 {int i;
 57   queue<int>Q;
 58   memset(f,0,sizeof(f));
 59   for (i=1;i<=n;i++)
 60     if (d[i]==0) Q.push(i),f[i]=0;
 61   while (Q.empty()==0)
 62     {
 63       int u=Q.front();
 64       Q.pop();
 65       ans=max(ans,f[u]);
 66       for (i=head2[u];i;i=edge2[i].next)
 67     {
 68       int v=edge2[i].to;
 69       d[v]--;
 70       f[v]=max(f[v],f[u]+edge2[i].dis);
 71       if (d[v]==0)
 72         {
 73           Q.push(v);
 74         }
 75     }
 76     }
 77 }
 78 int main()
 79 {int i,u,v,w,j;
 80   cin>>n>>m;
 81   cin>>s1>>t1>>s2>>t2;
 82   for (i=1;i<=m;i++)
 83     {
 84       scanf("%d%d%d",&u,&v,&w);
 85       add(u,v,w);
 86       add(v,u,w);
 87     }
 88   SPFA(s1,t1,1);
 89   SPFA(t1,s1,2);
 90   SPFA(s2,t2,3);
 91   SPFA(t2,s2,4);
 92   for (i=1;i<=n;i++)
 93     {
 94       for (j=head[i];j;j=edge[j].next)
 95     {
 96       int v=edge[j].to;
 97       if (dist[1][i]+edge[j].dis+dist[2][v]!=dist[1][t1]) continue;
 98       if (dist[3][i]+edge[j].dis+dist[4][v]!=dist[3][t2]) continue;
 99       add_Top(i,v,edge[j].dis);
100       d[v]++;
101     }
102     }
103   Top_sort();
104   SPFA(t2,s2,3);
105   SPFA(s2,t2,4);
106   memset(d,0,sizeof(d));
107   memset(head2,0,sizeof(head2));
108   for (i=1;i<=n;i++)
109     {
110       for (j=head[i];j;j=edge[j].next)
111     {
112       int v=edge[j].to;
113       if (dist[1][i]+edge[j].dis+dist[2][v]!=dist[1][t1]) continue;
114       if (dist[3][i]+edge[j].dis+dist[4][v]!=dist[3][s2]) continue;
115       add_Top(i,v,edge[j].dis);
116       d[v]++;
117     }
118     }
119   Top_sort();
120   cout<<ans;
121 }

 

posted @ 2017-10-21 16:11  Z-Y-Y-S  阅读(218)  评论(0编辑  收藏  举报