首页 > 代码库 > ZOJ3088 Easter Holidays spfa 最长路 最短路 路径打印

ZOJ3088 Easter Holidays spfa 最长路 最短路 路径打印

题目链接:

3088





题意:一个滑雪胜地包含了n 个地点,m 个滑雪斜坡,k 架雪橇,其中2≤n≤1000、1≤m≤1000、1≤k≤1000。滑雪斜坡和雪橇总是从一个地点到另一个地点:滑雪斜坡是从高地点到低地点,而雪橇刚好相反(注意,雪橇不能下降)。Per 是一个滑雪初学者,他很害怕雪橇,尽管他想滑得尽可能快。现在,他发现他可以选择不同的雪橇和滑雪斜坡。他现在想这样安排他的滑雪行程:

1) 从一架雪橇的起点出发并最终回到起点。
2) 这个过程分为两个阶段:第一阶段,乘坐一架或多架雪橇上升;第二阶段,一直滑下来直到起点
3) 可能少地避免惊慌。这样,如果花在滑坡斜面上的时间与花在乘坐和等候雪橇的时间的比率越大就越好。


你能帮Per 找到一条惊慌最少的行程吗?




题解:

求两段路程的最大比率     即为求第一段的最长路径和第二段的最短路径(spfa算法)   且它们的起点和终点刚好相反     然后通过spfa(遍历所有起点 用dis数组记录到达所有其他点的最长路和最短路,并用path数组记录路径),最后枚举所有起点终点  输出比率的最大值即可。



代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#define maxx 0x3f3f3f3f
using namespace std;
struct node{
    int to,w,pre;
} edge[2][1005];                  //一维0表示滑坡  1表示雪橇
int dis[2][1005][1005];           //dis   path的第二维表示所有起点
int path[2][1005][1005];                
int next[2][1005];
int vis[2][1005];
int loc[1005];                    //记录结果路径
int m,s1,s2;
void addedge(int x){
    int u,v,we,d;
    scanf("%d%d%d",&u,&v,&we);
    if(x==0)d=s1;
    else
        d=s2;
    edge[x][d].to=v;
    edge[x][d].w=we;
    edge[x][d].pre=next[x][u];
    next[x][u]=d;
    if(x==0)s1++;
    else
        s2++;
    return;
}
void spfa(int x,int start){
    queue<int>q;
    int head;
    dis[x][start][start]=0;
    q.push(start);
    while(!q.empty()){
        head=q.front();
        q.pop();
        vis[x][head]=0;
        for(int i=next[x][head]; i!=-1; i=edge[x][i].pre){
            int u=head,v=edge[x][i].to,we=edge[x][i].w;
            if(x==0){
                if(dis[x][start][v]<dis[x][start][u]+we){
                    dis[x][start][v]=dis[x][start][u]+we;
                    path[x][start][v]=u;
                    if(!vis[x][v]){
                        vis[x][v]=1;
                        q.push(v);
                    }
                }
            }
            else{
                if(dis[x][start][v]>dis[x][start][u]+we){
                    dis[x][start][v]=dis[x][start][u]+we;
                    path[x][start][v]=u;
                    if(!vis[x][v]){
                        vis[x][v]=1;
                        q.push(v);
                    }
                }
            }
        }
    }
    return;
}
int main(){
    int t,n,k,i,j;
    scanf("%d",&t);
    while(t--){
        s1=s2=0;
        scanf("%d%d%d",&m,&n,&k);
        for(i=1; i<=m; i++){
            next[0][i]=next[1][i]=-1;
            for(j=i; j<=m; j++){
                path[0][i][j]=path[1][i][j]=path[0][j][i]=path[1][j][i]=-1;
                dis[0][i][j]=dis[0][j][i]=0;
                dis[1][j][i]=dis[1][i][j]=maxx;
            }
        }
        while(n--){
            addedge(0);
        }
        while(k--){
            addedge(1);
        }
        for(i=1; i<=m; i++){
            memset(vis,0,sizeof(vis));
            spfa(0,i);
            spfa(1,i);
        }
        double ans=0,q1,q2,q3;
        int start,endd,s3=0,pos;
        for(i=1; i<=m; i++)
            for(j=1; j<=m; j++){
                if(i==j||dis[0][i][j]==0||dis[1][j][i]==maxx)
                    continue;
                q1=dis[0][i][j],q2=dis[1][j][i];
                q3=q1/q2;
                if(q3>ans)
                    {start=i,endd=j,ans=q3;}
            }
        pos=endd;
        while(path[0][start][pos]!=-1){
            loc[s3++]=pos;
            pos=path[0][start][pos];
        }
        while(path[1][endd][pos]!=-1){
            loc[s3++]=pos;
            pos=path[1][endd][pos];
        }
        cout<<endd;
        for(i=s3-1;i>=0;i--)
            cout<<' '<<loc[i];
        printf("\n%.3lf\n",ans);
    }
    return 0;
}


  

ZOJ3088 Easter Holidays spfa 最长路 最短路 路径打印