农场派对
题目描述
(N(1leq Nleq1000))头牛要去参加一场在编号为(x(1leq x leq N)) 的牛的农场举行的派对。有 (M(1leq M leq 100000))条有向道路,每条路长 (T_i(1leq T_ileq100));每头牛都必须参加完派对后回到家,每头牛都会选择最短路径。求这(N) 头牛的最短路径(一个来回)中最长的一条的长度。 特别提醒:可能有权值不同的重边。
输入描述
第(1)行: (3)个空格分开的整数 (N,M,X);
第(2.....M+1)行:(3)个空格分开的整数(A_i,B_i,T_i) ,表示有一条从(A_i)到 (B_i)的路,长度为 (T_i)。
输出描述
一行一个数,表示最长最短路的长度。
样例输入
4 8 2
1 2 4
1 3 2
1 4 7
2 1 1
2 3 5
3 1 2
3 4 4
4 2 3
样例输出
10
思路
本来在数据范围比较小的情况下,可以直接跑floyd算法,然后结算回路最大长度即可,但是在1000下时间复杂度(O(n^3))要运行(1e9)次,对于大多数情况下显然是不可以的(除了某些强的不行的OJ)。所以这里考虑用Dijkstra,来计算单源最短路,然后将边的方向调转,再计算一次单源最短路,就得出了去和回来的最短路径,相加即为来回的回路的最短长度,最后(O(N))寻找最大值即可。
代码
/****************************************************
/@Author: Kirito
/@TIME: 2020-04-30
/@FILENAME: partyatformzhengjie.cpp
/@REMARK:
/****************************************************/
#include <bits/stdc++.h>
#define lowbit(x) (x&(-x))
#define CSE(x,y) memset(x,y,sizeof(x))
#define INF 0x3f3f3f3f
#define Abs(x) (x>=0?x:(-x))
#define FAST ios::sync_with_stdio(false);cin.tie(0);
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
typedef pair<ll , ll> pll;
const int maxn=211111;
//graph1
int first[maxn],nxt1[maxn],u[maxn],v[maxn];
int mpp[1005][1005],n,m,s,cnt1;
//graph2
int head[maxn],nxt2[maxn],l[maxn],r[maxn];
int mpw[1005][1005],cnt2;
//spfa-box
int dist1[maxn],book[maxn],dist2[maxn];
//邻接表
void add(int x,int y){
cnt1++;cnt2++;
u[cnt1]=x;v[cnt1]=y;l[cnt2]=y;r[cnt2]=x;
nxt1[cnt1]=first[u[cnt1]];first[u[cnt1]]=cnt1;
nxt2[cnt2]=head[l[cnt2]];head[l[cnt2]]=cnt2;
return;
}
void spfa1(){
CSE(dist1,INF);CSE(book,0);
queue<int>point;
dist1[s]=0;book[s]=1;point.push(s);
while(!point.empty()){
int x=point.front();point.pop();book[x]=0;
for(int i=first[x];i!=-1;i=nxt1[i]){
//可加判断是否wu解
int y=v[i],w=mpp[x][y];
if(dist1[y]>dist1[x]+w){
dist1[y]=dist1[x]+w;
if(!book[y]){
point.push(y);book[y]=1;
}
}
}
}
return;
}
void spfa2(){
CSE(dist2,INF);CSE(book,0);
queue<int>point;
dist2[s]=0;book[s]=1;point.push(s);
while(!point.empty()){
int x=point.front();point.pop();book[x]=0;
for(int i=head[x];i!=-1;i=nxt2[i]){
//可加判断是否wu解
int y=r[i],w=mpw[x][y];
if(dist2[y]>dist2[x]+w){
dist2[y]=dist2[x]+w;
if(!book[y]){
point.push(y);book[y]=1;
}
}
}
}
return;
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("in.in","r",stdin);
#endif
FAST;
cin>>n>>m>>s;
CSE(first,-1);CSE(nxt1,-1);CSE(nxt2,-1);CSE(head,-1);
CSE(mpp,INF);CSE(mpw,INF);
for(int i=0;i<m;i++){
int x,y,w;
cin>>x>>y>>w;
if(w<mpp[x][y]){
mpp[x][y]=w;
add(x,y);
mpw[y][x]=w;
}
}
spfa1();spfa2();
int ans=0;
for(int i=1;i<=n;i++){
ans=max(ans,dist1[i]+dist2[i]);
}
cout<<ans<<endl;
return 0;
}
代码中用的是spfa算法,道理和Dijkstra是一样的