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;
}
时间: 2024-08-04 03:21:03

ZOJ3088 Easter Holidays spfa 最长路 最短路 路径打印的相关文章

Zoj 3088 Easter Holidays SPFA+枚举

其实就是枚举最高点和起点,然后以最高点为源点在两张图上分别做spfa.一遍最短路,一遍最长路. 暴露出来的问题:思维不够清晰,代码能力还不够 #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> #include <climits> #include <string> #include <iostream> #include &

[BZOJ1663] [Usaco2006 Open]赶集(spfa最长路)

传送门 按照时间t排序 如果 t[i] + map[i][j] <= t[j],就在i和j之间连一条边 然后spfa找最长路 #include <queue> #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #define N 401 using namespace std; int n, ans, cnt; int a[N][N],

HDU 6201 2017沈阳网络赛 树形DP或者SPFA最长路

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6201 题意:给出一棵树,每个点有一个权值,代表商品的售价,树上每一条边上也有一个权值,代表从这条边经过所需要的花费.现在需要你在树上选择两个点,一个作为买入商品的点,一个作为卖出商品的点,当然需要考虑从买入点到卖出点经过边的花费.使得收益最大.允许买入点和卖出点重合,即收益最小值为0. 解法:我们设1为根节点,假设一开始一个人身上的钱为0.我们设dp[i][0]表示从根节点走到i及其子树并中任一点买

2017 ACM/ICPC Asia Regional Shenyang Online spfa+最长路

transaction transaction transaction Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 132768/132768 K (Java/Others)Total Submission(s): 1496    Accepted Submission(s): 723 Problem Description Kelukin is a businessman. Every day, he travels arou

transaction transaction transaction 最大费用最大流转化到SPFA最长路

//当时比赛的时候没有想到可以用SPFA做,TLE! Problem Description Kelukin is a businessman. Every day, he travels around cities to do some business. On August 17th, in memory of a great man, citizens will read a book named "the Man Who Changed China". Of course, K

缩点+spfa最长路【bzoj】 1179: [Apio2009]Atm

[bzoj] 1179: [Apio2009]Atm Description Siruseri 城中的道路都是单向的.不同的道路由路口连接.按照法律的规定, 在每个路口都设立了一个 Siruseri 银行的 ATM 取款机.令人奇怪的是,Siruseri 的酒吧也都设在路口,虽然并不是每个路口都设有酒吧.Banditji 计划实施 Siruseri 有史以来最惊天动地的 ATM 抢劫.他将从市中心 出发,沿着单向道路行驶,抢劫所有他 途径的 ATM 机,最终他将在一个酒吧庆 祝他的胜利.使用高超

hdu 1317 SPFA+连通判断+最长路

Description It has recently been discovered how to run open-source software on the Y-Crate gaming device. A number of enterprising designers have developed Advent-style games for deployment on the Y-Crate. Your job is to test a number of these design

【强联通分量缩点】【最长路】【spfa】CH Round #59 - OrzCC杯NOIP模拟赛day1 队爷的讲学计划

10分算法:对于城市网络为一条单向链的数据, 20分算法:对于n<=20的数据,暴力搜出所有的可能路径. 结合以上可以得到30分. 60分算法:分析题意可得使者会带着去的城市也就是这个城市所在强联通分量的其他城市,这个过程的代价也就是这个强联通分量的城市数-1,且他可以选择任何一个其中的城市离开这个强联通分量.于是我们求出所有强联通分量,记录下每一个包含的城市数,然后缩点.接下来再用dfs,由于数据是构造的,只能得到60分. 100分算法:在缩点之后,这个图变成了一个有向无环图,我们将一条边连向

P1807 最长路_NOI导刊2010提高(07)

P1807 最长路_NOI导刊2010提高(07) 题目描述 设G为有n个顶点的有向无环图,G中各顶点的编号为1到n,且当为G中的一条边时有i < j.设w(i,j)为边的长度,请设计算法,计算图G中<1,n>间的最长路径. 输入输出格式 输入格式: 输入文件longest.in的第一行有两个整数n和m,表示有n个顶点和m条边,接下来m行中每行输入3个整数a,b,v(表示从a点到b点有条边,边的长度为v). 输出格式: 输出文件longest.out,一个整数,即1到n之间的最长路径.如