题意:有一滑雪场,前m条路径为从上往下滑雪,后k条路径为电梯,求从某点出发回到该点的路径中t(滑雪)/t(电梯)值最大的,
分析:题目要求任意两点最长路及最短路,而且要求输出路径,数据大小为
(2 <= n <= 1000, 1 <= m <= 1000, 1 <= k <= 1000),floyd及bellman都不能输出路径,
dijkstra的话需要用n次,n^3的时间复杂度绝对超时,spfa时间复杂度O(km) m为边数 k一般为2或3,就是他了,n次spfa求最短(长)路并记录路径。
AC代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<queue>
#include<map>
#include<cmath>
#define INF 0x3f3f3f3f
using namespace std;
const int MAXN=1005;
const int MAXM=2055;
int n,cnt,dis1[MAXN][MAXN],p1[MAXN][MAXN],inq[MAXN],first1[MAXN],dis2[MAXN][MAXN],p2[MAXN][MAXN],first2[MAXN];
int u[MAXM],v[MAXM],w[MAXM],next1[MAXM],next2[MAXM];
void spfa1(int x,int *dis,int *p,int* first,int *next)//最短路
{
queue<int>q;
memset(dis,0x3f,MAXN*sizeof(int));
memset(inq,0,MAXN*sizeof(int));
q.push(x);
dis[x]=0;
inq[x]=1;
p[x]=-1;
while(!q.empty())
{
int e,x=q.front();q.pop();
inq[x]=0;
for(e=first[x];e!=-1;e=next[e])
if(dis[x]+w[e]<dis[v[e]])
{
dis[v[e]]=dis[x]+w[e];
p[v[e]]=x;
if(!inq[v[e]])
{
q.push(v[e]);
inq[v[e]]=1;
}
}
}
}
void spfa(int x,int dis[],int p[],int* first,int *next)//最长路
{
queue<int>q;
memset(dis,0,MAXN*sizeof(int));
memset(inq,0,MAXN*sizeof(int));
q.push(x);
dis[x]=0;
inq[x]=1;
p[x]=-1;
while(!q.empty())
{
int e,x=q.front();q.pop();
inq[x]=0;
for(e=first[x];e!=-1;e=next[e])
if(dis[x]+w[e]>dis[v[e]])
{
dis[v[e]]=dis[x]+w[e];
p[v[e]]=x;
if(!inq[v[e]])
{
q.push(v[e]);
inq[v[e]]=1;
}
}
}
}
void add_(int a,int b,int c,int *first,int *next)
{
u[cnt]=a;
v[cnt]=b;
w[cnt]=c;
next[cnt]=first[a];
first[a]=cnt++;
}
void showpath(int *p,int x)
{
if(x==-1)return ;
showpath(p,p[x]);
printf("%d ",x);
}
int main()
{
int N,m,k,i,j;
cin>>N;
while(N--)
{
scanf("%d%d%d",&n,&m,&k);
int a,b,c;
cnt=0;
memset(first1,-1,sizeof first1);
memset(next1,-1,sizeof next1);
memset(first2,-1,sizeof first2);
memset(next2,-1,sizeof next2);
for(i=0;i<m;i++)
{
scanf("%d%d%d",&a,&b,&c);
add_(a,b,c,first1,next1);
}
for(i=0;i<k;i++)
{
scanf("%d%d%d",&a,&b,&c);
add_(a,b,c,first2,next2);
}
for(i=1;i<=n;i++)
{
spfa(i,dis1[i],p1[i],first1,next1);
spfa1(i,dis2[i],p2[i],first2,next2);
}
double ans=0;int ans1,ans2;
for(i=1;i<=n;i++)
for(j=1;j<=n;j++)
if(i!=j&&dis2[j][i]!=INF){
if(ans<dis1[i][j]*1.0/dis2[j][i])ans=dis1[i][j]*1.0/dis2[j][i],ans1=i,ans2=j;
}
showpath(p2[ans2],p2[ans2][ans1]);
showpath(p1[ans1],p1[ans1][ans2]);
printf("%d\n%.3lf\n",ans2,(int)(1000*(ans)+0.5)*1.0/1000);
}
return 0;
}