例题5.11 机场快线 UVa11374

来源:互联网 发布:android文件管理器源码 编辑:程序博客网 时间:2024/04/20 09:52

1.题目描述:点击打开链接

2.解题思路:本题利用最短路求解。因为商业线只有一站,因此我们希望枚举所有可能情况,然后看哪一种是最优方案。此时可以考虑先用Dijkstra算法求出从起点出发的最短路d1,和从终点出发的最短路d2。即d1[i]表示从起点走到i的最短路,d2[i]表示从i走到终点的最短路,设当前的商业线起点为a,终点为b,时间为T(a,b),那么总时间就是d1[a]+T(a,b)+d2[b]。因为预处理的时间是O(mlogn),因此总的时间复杂度是O(MlogN+K)。

注意:在枚举时候需要考虑从a->b和b->a两种走法。

3.代码:

#include<iostream>#include<algorithm>#include<cassert>#include<string>#include<sstream>#include<set>#include<bitset>#include<vector>#include<stack>#include<map>#include<queue>#include<deque>#include<cstdlib>#include<cstdio>#include<cstring>#include<cmath>#include<ctime>#include<cctype>#include<list>#include<complex>#include<functional>using namespace std;#define me(s)  memset(s,0,sizeof(s))#define rep(i,n) for(int i=0;i<(n);i++)#define pb push_backtypedef long long ll;typedef unsigned int uint;typedef unsigned long long ull;typedef pair <int,int> P;const int INF=1000000000;const int N=500+10;struct Edge{int from,to,dist;};struct Dijkstra{    int n,m;    vector<int>g[N];    vector<Edge>edges;    int p[N],d[N];    void init(int n)    {        this->n=n;        me(g);edges.clear();    }    void addedge(int u,int v,int dist)    {        edges.push_back(Edge{u,v,dist});        m=edges.size();        g[u].push_back(m-1);    }    void dijkstra(int s)    {        fill(d,d+n,INF);        d[s]=0;        priority_queue<P,vector<P>,greater<P> >q;        q.push(P(0,s));        while(!q.empty())        {            P x=q.top();q.pop();            int u=x.second;            if(d[u]<x.first)continue;            for(int i=0;i<g[u].size();i++)            {                int id=g[u][i];                Edge&e=edges[id];                if(d[e.to]>d[u]+e.dist)                {                    d[e.to]=d[u]+e.dist;                    p[e.to]=id;                    q.push(P(d[e.to],e.to));                }            }        }    }    void GetSP(int s,int*dist,vector<int>*paths)//paths[i]保存从起点s到i经过的结点编号    {        dijkstra(s);        for(int i=0;i<n;i++)        {            dist[i]=d[i];            paths[i].clear();            int t=i;            paths[i].pb(t);            while(t!=s)            {                paths[i].pb(edges[p[t]].from);                t=edges[p[t]].from;            }            reverse(paths[i].begin(),paths[i].end());        }    }};Dijkstra solver;int d1[N],d2[N];vector<int>paths1[N],paths2[N];int main(){    int rnd=0;    int n,s,e,m,k,x,y,z;    while(~scanf("%d%d%d%d",&n,&s,&e,&m))    {        solver.init(n);        s--,e--;        for(int i=0;i<m;i++)        {            scanf("%d%d%d",&x,&y,&z);            x--,y--;            solver.addedge(x,y,z);            solver.addedge(y,x,z);        }        solver.GetSP(s,d1,paths1);        solver.GetSP(e,d2,paths2);        int ans=d1[e];        vector<int>path=paths1[e];        int midpoint=-1; //初始化时候不使用商业线        scanf("%d",&k);        for(int i=0;i<k;i++)        {            scanf("%d%d%d",&x,&y,&z);            x--,y--;            for(int j=0;j<2;j++)            {                if(d1[x]+d2[y]+z<ans)                {                    ans=d1[x]+d2[y]+z;                    path=paths1[x];                    for(int j=paths2[y].size()-1;j>=0;j--)                        path.push_back(paths2[y][j]);                    midpoint=x;                }                swap(x,y); //注意考虑从y到达x的情况            }        }        if(rnd++)puts("");        for(int i=0;i<path.size()-1;i++)            printf("%d ",path[i]+1);        printf("%d\n",e+1);        if(midpoint==-1)puts("Ticket Not Used");        else printf("%d\n",midpoint+1);        printf("%d\n",ans);    }}


0 0
原创粉丝点击