BZOJ1880 [Sdoi2009]Elaxia的路线 【最短路 + dp】
题目
最近,Elaxia和w的关系特别好,他们很想整天在一起,但是大学的学习太紧张了,他们 必须合理地安排两个人在一起的时间。Elaxia和w每天都要奔波于宿舍和实验室之间,他们 希望在节约时间的前提下,一起走的时间尽可能的长。 现在已知的是Elaxia和w**所在的宿舍和实验室的编号以及学校的地图:地图上有N个路 口,M条路,经过每条路都需要一定的时间。 具体地说,就是要求无向图中,两对点间最短路的最长公共路径。
输入格式
第一行:两个整数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。 出出出格格格式式式::: 一行,一个整数,表示每天两人在一起的时间(即最长公共路径的长度)。
输出格式
一行,一个整数,表示每天两人在一起的时间(即最长公共路径的长度)
输入样例
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
输出样例
3
提示
对于30%的数据,N ≤ 100;
对于60%的数据,N ≤ 1000;
对于100%的数据,N ≤ 1500,输入数据保证没有重边和自环。
题解
最后的路径为公共的最短路,所以我们先将第一对点的所有最短路边建成一个新的拓扑图
然后就可以在新图上dp了
设\(f[i]\)为第一对点走到\(i\)时的最大公共最短路长
显然\(f[i] = max{f[j] + edge.w}\)【\(j\)为\(i\)拓扑图中的前驱点且i-j这条边在第二对点的最短路上】
#include<iostream> #include<cmath> #include<cstdio> #include<queue> #include<cstring> #include<algorithm> #define LL long long int #define REP(i,n) for (int i = 1; i <= (n); i++) #define Redge(u) for (int k = h[u],to; k; k = ed[k].nxt) #define BUG(s,n) for (int i = 1; i <= (n); i++) cout<<s[i]<<' '; puts(""); using namespace std; const int maxn = 1505,maxm = 3000005,INF = 1000000000; inline int read(){ int out = 0,flag = 1; char c = getchar(); while (c < 48 || c > 57) {if (c == '-') flag = -1; c = getchar();} while (c >= 48 && c <= 57) {out = (out << 3) + (out << 1) + c - '0'; c = getchar();} return out * flag; } int h[maxn],ne = 2; struct EDGE{int from,to,nxt,w,f;}ed[maxm]; inline void build(int u,int v,int w){ ed[ne] = (EDGE){u,v,h[u],w}; h[u] = ne++; ed[ne] = (EDGE){v,u,h[v],w}; h[v] = ne++; } int n,m,S1,T1,S2,T2; int d[4][maxn],vis[maxn]; struct node{int u,d;}; inline bool operator <(const node& a,const node& b){return a.d > b.d;} priority_queue<node> q; void dijkstra(int S,int p){ for (int i = 1; i <= n; i++) d[p][i] = INF,vis[i] = false; d[p][S] = 0; node u; q.push((node){S,d[p][S]}); while (!q.empty()){ u = q.top(); q.pop(); if (vis[u.u]) continue; vis[u.u] = true; Redge(u.u) if (!vis[to = ed[k].to] && d[p][to] > d[p][u.u] + ed[k].w){ d[p][to] = d[p][u.u] + ed[k].w; q.push((node){to,d[p][to]}); } } } int de[maxn],f[maxn]; queue<int> Q; void solve(){ dijkstra(S1,0); dijkstra(T1,1); dijkstra(S2,2); dijkstra(T2,3); for (int k = 2; k < ne; k++) if (d[0][ed[k].from] + ed[k].w + d[1][ed[k].to] == d[0][T1]) ed[k].f = true,de[ed[k].to]++; Q.push(S1); int u; while (!Q.empty()){ u = Q.front(); Q.pop(); Redge(u) if (ed[k].f){ if (d[2][u] + ed[k].w + d[3][to = ed[k].to] == d[2][T2] || d[3][u] + ed[k].w + d[2][to = ed[k].to] == d[2][T2]) f[to] = max(f[to],f[u] + ed[k].w); if (!(--de[to])) Q.push(to); } } int ans = 0; for (int i = 1; i <= n; i++) ans = max(ans,f[i]); printf("%d\n",ans); } int main(){ n = read(); m = read(); S1 = read(); T1 = read(); S2 = read(); T2 = read(); int a,b,w; for (int i = 1; i <= m; i++){ a = read(); b = read(); w = read(); build(a,b,w); } solve(); return 0; }
- [BZOJ1880][Sdoi2009] Elaxia的路线 (最短路,拓扑排序)
- bzoj 1880 [Sdoi2009]Elaxia的路线(最短路+拓扑序)
- BZOJ1880: [Sdoi2009]Elaxia的路线(最短路)
- 【BZOJ 1880】 [Sdoi2009]Elaxia的路线 (最短路树)
- (bzoj 1880 [Sdoi2009]Elaxia的路线)<最短路+拓扑最长链>
- [BZOJ1880][Sdoi2009]Elaxia的路线(最短路+拓扑序)
- BZOJ 1880: [Sdoi2009]Elaxia的路线( 最短路 + dp )
- bzoj 1880: [Sdoi2009]Elaxia的路线 最短路
- bzoj1880 [Sdoi2009]Elaxia的路线
- BZOJ 1880 [Sdoi2009]Elaxia的路线 - SPFA+拓扑排序
- [BZOJ1880][SDOI2009]Elaxia的路线(SPFA+拓扑排序+DP)
- 【BZOJ1880】【SDOI2009】Elaxia的路线
- bzoj1880 [Sdoi2009]Elaxia的路线
- BZOJ1880: [Sdoi2009]Elaxia的路线
- BZOJ 1880 Sdoi2009 Elaxia的路线 SPFA+拓扑排序
- bzoj1880: [Sdoi2009]Elaxia的路线
- bzoj 1880: [Sdoi2009]Elaxia的路线【spfa+拓扑排序】
- BZOJ1880[Sdoi2009]Elaxia的路线 spfa+拓扑序
- 【39.87%】【BZOJ 1880】[Sdoi2009]Elaxia的路线
- BZOJ1880: [Sdoi2009]Elaxia的路线|dijksrtra|暴力