标签:spfa 现在 set eof algorithm 起点 inf print pre
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,输入数据保证没有重边和自环。
直接上4遍SPFA,然后找到同为两条最短路上的边,进行拓扑排序,找到最大值。做完之后记得将某条路径的起点和终点交换再做一次
/*program from Wolfycz*/
#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define inf 0x7f7f7f7f
using namespace std;
typedef long long ll;
typedef unsigned int ui;
typedef unsigned long long ull;
inline int read(){
int x=0,f=1;char ch=getchar();
for (;ch<'0'||ch>'9';ch=getchar()) if (ch=='-') f=-1;
for (;ch>='0'&&ch<='9';ch=getchar()) x=(x<<1)+(x<<3)+ch-'0';
return x*f;
}
inline void print(int x){
if (x>=10) print(x/10);
putchar(x%10+'0');
}
const int N=1.5e3,M=5e5;
struct S1{
int pre[(M<<1)+10],now[N+10],child[(M<<1)+10],val[(M<<1)+10],tot;
S1(){tot=0;memset(now,0,sizeof(now));}
void init(){tot=0,memset(now,0,sizeof(now));}
void join(int x,int y,int z){pre[++tot]=now[x],now[x]=tot,child[tot]=y,val[tot]=z;}
void insert(int x,int y,int z){join(x,y,z),join(y,x,z);}
}Old,New;
struct S2{
int dis[N+10];
S2(){memset(dis,63,sizeof(dis));}
}Frw_1,Frw_2,Bck_1,Bck_2;
int h[N+10],F[N+10],deg[N+10];
int Ans,Dis_1,Dis_2,n,m;
bool vis[N+10];
void SPFA(int x,int *dis){
int head=0,tail=1;
h[1]=x,dis[x]=0,vis[x]=1;
while (head!=tail){
if (++head>N) head=1;
int Now=h[head];
for (int p=Old.now[Now],son=Old.child[p];p;p=Old.pre[p],son=Old.child[p]){
if (dis[son]>dis[Now]+Old.val[p]){
dis[son]=dis[Now]+Old.val[p];
if (!vis[son]){
if (++tail>N) tail=1;
vis[h[tail]=son]=1;
}
}
}
vis[Now]=0;
}
}
bool check_1(int x,int y,int v){return Frw_1.dis[x]+v+Bck_1.dis[y]==Dis_1;}
bool check_2(int x,int y,int v){return Frw_2.dis[x]+v+Bck_2.dis[y]==Dis_2;}
void Get_Ans(int S_1,int T_1,int S_2,int T_2){
New.init();
memset(F,0,sizeof(F));
memset(deg,0,sizeof(deg));
for (int x=1;x<=n;x++)
for (int p=Old.now[x],son=Old.child[p];p;p=Old.pre[p],son=Old.child[p])
if (check_1(x,son,Old.val[p])&&check_2(x,son,Old.val[p]))
New.join(x,son,Old.val[p]),deg[son]++;
int head=1,tail=0;
for (int i=1;i<=n;i++) if (!deg[i]) h[++tail]=i;
for (;head<=tail;head++){
int Now=h[head];
for (int p=New.now[Now],son=New.child[p];p;p=New.pre[p],son=New.child[p]){
F[son]=max(F[son],F[Now]+New.val[p]);
if (!(--deg[son])) h[++tail]=son;
}
}
for (int i=1;i<=n;i++) Ans=max(Ans,F[i]);
}
int main(){
n=read(),m=read();
int S_1=read(),T_1=read(),S_2=read(),T_2=read();
for (int i=1;i<=m;i++){
int x=read(),y=read(),z=read();
Old.insert(x,y,z);
}
SPFA(S_1,Frw_1.dis);
SPFA(S_2,Frw_2.dis);
SPFA(T_1,Bck_1.dis);
SPFA(T_2,Bck_2.dis);
Dis_1=Frw_1.dis[T_1];
Dis_2=Frw_2.dis[T_2];
Get_Ans(S_1,T_1,S_2,T_2);
swap(Frw_1,Bck_1);
Get_Ans(T_1,S_1,S_2,T_2);
printf("%d\n",Ans);
return 0;
}
标签:spfa 现在 set eof algorithm 起点 inf print pre
原文地址:https://www.cnblogs.com/Wolfycz/p/9744429.html