BZOJ1880: [Sdoi2009]Elaxia的路线(最短路)
1880: [Sdoi2009]Elaxia的路线
Time Limit: 4 Sec Memory Limit: 64 MB
Submit: 2049 Solved: 805
题目链接:https://www.lydsy.com/JudgeOnline/problem.php?id=1880
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
题解:
由于题目中有两个起点和终点,我们直接从每一个点出发跑一遍最短路。由于范围只有1500,所以我们可以直接枚举两个点,然后根据这两个点来计算维护一下答案就好了。
具体看代码吧,证明应该还是比较简单的。因为如果从s1出发到i点的最短路记做d1,从t1到j点的最短路记作d2,他们之间的最短路距离为d,那么说明i和j之间的最短路为d-d1-d2。
如果此时s2,t2对于i,j两点同样满足上面的等式,即d'-d1'-d2'为i,j两点之间的最短路,那么说明这时i,j之间的最短路即为公共路径。
代码如下:
#include <cstdio> #include <cstring> #include <algorithm> #include <iostream> #include <cmath> #include <queue> #define INF 0x3f3f3f3f using namespace std; typedef long long ll; const int M = 4000005,N = 1505 ; int n,m; int s1,s2,t1,t2; struct Edge{ int u,v,w,next ; }e[M]; int tot; int head[N],d[4][N],vis[N]; struct node{ int u; ll d; bool operator < (const node &A)const{ return d>A.d; } }; void adde(int u,int v,int w){ e[tot].v=v;e[tot].w=w;e[tot].next=head[u];head[u]=tot++; } void Dijkstra(int s,int id){ priority_queue <node> q;memset(d[id],INF,sizeof(d[id])); memset(vis,0,sizeof(vis));d[id][s]=0; q.push(node{s,0}); while(!q.empty()){ node cur = q.top();q.pop(); int u=cur.u; if(vis[u]) continue ; vis[u]=1; for(int i=head[u];i!=-1;i=e[i].next){ int v=e[i].v; if(d[id][v]>d[id][u]+(ll)e[i].w){ d[id][v]=d[id][u]+(ll)e[i].w; q.push(node{v,d[id][v]}); } } } } int main(){ ios::sync_with_stdio(false);cin.tie(0); cin>>n>>m; cin>>s1>>t1>>s2>>t2; memset(head,-1,sizeof(head)); for(int i=1;i<=m;i++){ int u,v,w; cin>>u>>v>>w; adde(u,v,w);adde(v,u,w); } Dijkstra(s1,0);Dijkstra(t1,1); Dijkstra(s2,2);Dijkstra(t2,3); int mn1=d[0][t1],mn2=d[2][t2]; //cout<<mn1<<" "<<mn2<<endl; int ans = 0; for(int i=1;i<=n;i++){ for(int j=1;j<=n;j++){ if(i==j) continue ; int need = mn1-d[0][i]-d[1][j]; if(mn2-d[2][i]-d[3][j]==need||mn2-d[2][j]-d[3][i]==need){ ans=max(ans,need); } } } cout<<ans; return 0; }
重要的是自信,一旦有了自信,人就会赢得一切。