zoukankan      html  css  js  c++  java
  • UVA 11374 Airport Express 机场快线(单源最短路,dijkstra,变形)

    题意:

      给一幅图,要从s点要到e点,图中有两种无向边分别在两个集合中,第一个集合是可以无限次使用的,第二个集合中的边只能挑1条。问如何使距离最短?输出路径,用了第二个集合中的哪条边,最短距离。

    思路:

    (1)简单易操作方法:既然第二个集合的边只能有1条,就穷举下这些边,可能的边集进行求最短路,同时记录3个答案。复杂度是O(m*k)。

    (2)时间复杂度低:不妨先求从s到每个其他点的距离d1[i],再求e到其他每个点的距离d2[i],接下来穷举第二个集合中的每条边u-v,那么最短距离为d1[u]+dis[u][v]+d2[v],注意边是无向的。麻烦在记录路径而已,还是挺容易操作的。复杂度是O(2m+k)。

    下面是第一种方法的代码:

      1 #include <bits/stdc++.h>
      2 #define LL long long
      3 #define pii pair<int,int>
      4 #define INF 0x7f7f7f7f
      5 using namespace std;
      6 const int N=1010;
      7 int n, m, k;
      8 vector<int> vect[N];
      9 int edge_cnt;
     10 struct node
     11 {
     12     int from, to, dis, tag;
     13     node(){};
     14     node(int from,int to,int dis,int tag):from(from),to(to),dis(dis),tag(tag){};
     15 }edge[N*5];
     16 
     17 
     18 
     19 void add_node(int from,int to,int dis,int tag)
     20 {
     21     edge[edge_cnt]=node(from,to,dis,tag);
     22     vect[from].push_back(edge_cnt++);
     23 }
     24 
     25 
     26 int tag[N], dist[N], vis[N], path[N];
     27 int dijkstra(int s,int e)
     28 {
     29     memset(dist,0x7f,sizeof(dist));
     30     memset(tag,0,sizeof(tag));
     31     memset(vis,0,sizeof(vis));
     32     memset(path,0,sizeof(path));
     33 
     34     priority_queue<pii,vector<pii>,greater<pii> > que;
     35     que.push(make_pair(0, s));
     36     dist[s]=0;
     37 
     38     while(!que.empty())
     39     {
     40         int x=que.top().second;
     41         que.pop();
     42         if(vis[x])  continue;
     43         vis[x]=1;
     44         for(int i=0; i<vect[x].size(); i++)
     45         {
     46             node e=edge[vect[x][i]];
     47             if( e.tag>0 && dist[e.to]>dist[x]+e.dis )
     48             {
     49                 dist[e.to]=dist[x]+e.dis;
     50                 path[e.to]=x;
     51                 if(e.tag==2)
     52                 {
     53                     tag[e.to]=true; //到这个点用了快线
     54                 }
     55                 que.push( make_pair(dist[e.to],e.to) );
     56             }
     57         }
     58     }
     59     return dist[e];
     60 }
     61 
     62 void cal(int s ,int e)
     63 {
     64     vector<int> ans;
     65     int quick=0, big=dijkstra(s,e), d=e;//先跑了一遍不用快线的
     66 
     67     while( d )
     68     {
     69         ans.push_back(d);
     70         d=path[d];
     71     }
     72 
     73     for(int i=m*2; i<(m+k)*2; i+=2 )   //穷举每条可以用的快线
     74     {
     75         edge[i].tag=2;
     76         edge[i+1].tag=2;
     77 
     78         int dis=dijkstra(s,e);
     79         if( dis<big )
     80         {
     81             big=dis;
     82             ans.clear();
     83             int ed=e, tmp=0;
     84             while( ed )
     85             {
     86                 if( tag[ed] )    tmp=path[ed];    //有可能没有用到
     87                 ans.push_back(ed);
     88                 ed=path[ed];
     89             }
     90             quick=tmp;//如果没有用到,也会及时更新为0
     91         }
     92         edge[i].tag=0;
     93         edge[i+1].tag=0;
     94     }
     95 
     96     reverse(ans.begin(),ans.end());
     97     printf("%d",ans[0]);    //千万注意输出格式
     98     for(int i=1; i<ans.size(); i++)    printf(" %d",ans[i]);
     99     printf("
    ");
    100 
    101     if(quick) printf("%d
    ",quick);
    102     else puts("Ticket Not Used");//别忘了
    103 
    104     printf("%d
    ",big);
    105 }
    106 
    107 int main()
    108 {
    109     freopen("input.txt", "r", stdin);
    110     int s=0, e, a, b, c, ttt=0;
    111     while(~scanf("%d%d%d", &n, &s, &e))
    112     {
    113         if(ttt)   printf("
    ");ttt++;//格式啊!
    114         edge_cnt=0;
    115         memset(edge,0,sizeof(edge));
    116         for(int i=0; i<=n; i++) vect[i].clear();
    117         scanf("%d",&m);
    118         for(int i=0; i<m; i++)
    119         {
    120             scanf("%d%d%d",&a,&b,&c);
    121             add_node(a,b,c,1);
    122             add_node(b,a,c,1);
    123         }
    124         scanf("%d",&k);
    125         for(int i=0; i<k; i++)
    126         {
    127             scanf("%d%d%d",&a,&b,&c);
    128             add_node(a,b,c,0);
    129             add_node(b,a,c,0);
    130         }
    131         cal(s,e);
    132     }
    133     return 0;
    134 }
    AC代码
  • 相关阅读:
    Elasticsearch 架构解析与最佳实践
    Redis一键安装脚本
    Android——GridView(网格视图)相关知识总结贴
    Android——TabHost(标签容器)相关知识总结贴
    Android——RatingBar(评价条)相关知识总结贴
    Android——SeekBar(拖动条)相关知识总结贴
    Android——SQLite/数据库 相关知识总结贴
    Android——媒体库 相关知识总结贴
    Android——Broadcast Receive 相关知识总结贴
    Android——进程通信/ AIDL/Message相关知识总结贴
  • 原文地址:https://www.cnblogs.com/xcw0754/p/4673006.html
Copyright © 2011-2022 走看看