第六章 图论 8 AcWing 1624. 地铁地图

第六章 图论 8 AcWing 1624. 地铁地图

原题链接

AcWing 1624. 地铁地图

算法标签

图论 单源最短路 dijkstra spfa

思路

若采用邻接矩阵存储
在这里插入图片描述
超出本题空间限制,因此无法采用邻接矩阵存储,可采用邻接表存储
若采用常规建图方式(即相邻两点之间建一条边)
在这里插入图片描述
采用另一种建图方式 若两点可达 建立双向边
在这里插入图片描述
最多需要建立边数
在这里插入图片描述
对于最短路问题 通常可存储的边数与点数
在这里插入图片描述
在这里插入图片描述
若采用常规dijkstra,算法时间复杂度O(n*m),由于时间限制:0.4s,将会超时
在这里插入图片描述
因此采用堆优化版dijkstra(常规dijkstra瓶颈在于寻找最小值的点,堆优化版dijkstra将所有未寻找放置堆中,堆中寻找最小值时间复杂度为O(log(1),更新最小值时间复杂度为O(log(n)),算法时间复杂度O(m*log(n)),由于时间限制:0.4s,可通过

由于可能会存在回路,对于回路,路径长度

在这里插入图片描述

代码

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#include<bits/stdc++.h>
#define int long long
#define x first
#define y second
#define ump unordered_map
#define pq priority_queue
#define rep(i, a, b) for(int i=a;i<b;++i)
#define Rep(i, a, b) for(int i=a;i>=b;--i)
using namespace std;
typedef pair<int, int> PII;
const int N = 10005;
//int t, n, m, cnt, ans;
string info[N];
int h[N], ne[N*100], e[N*100], w[N*100], line[N*100], stop[N], dist[N], cnt[N], pre[N], idx;
bool st[N];
int n, m;
inline int rd(){
   int s=0,w=1;
   char ch=getchar();
   while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
   while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();
   return s*w;
}
void put(int x) {
    if(x<0) putchar('-'),x=-x;
    if(x>=10) put(x/10);
    putchar(x%10^48);
} 
string format(int x){
    char res[5];
    sprintf(res, "%04lld", x);
    return res;
}
void add(int a, int b, int c, int id){
    e[idx]=b, w[idx]=c, line[idx]=id, ne[idx]=h[a], h[a]=idx++;
}
void dij(int S, int T){
    memset(dist, 0x3f, sizeof dist);
    memset(cnt, 0x3f, sizeof cnt);
    memset(st, 0, sizeof st);
    pq<PII, vector<PII>, greater<PII>> heap;
    heap.push({0, S});
    dist[S]=cnt[S]=0;
    while(heap.size()){
        auto t=heap.top();
        heap.pop();
        int val=t.y;
        if(val==T){
            break;
        }
        if(st[val]){
            continue;
        }
        st[val]=true;
        for(int i=h[val]; ~i; i=ne[i]){
            int j=e[i];
            if(dist[j]>dist[val]+w[i]){
                dist[j]=dist[val]+w[i];
                cnt[j]=cnt[val]+1;
                pre[j]=val;
                info[j]="Take Line#"+to_string(line[i])+" from "+format(val)+" to "+format(j)+ ".";
                heap.push({dist[j], j});
            }else if(dist[j]==dist[val]+w[i]){
                if(cnt[j]>cnt[val]+1){
                    cnt[j]=cnt[val]+1;
                    pre[j]=val;
                    info[j]="Take Line#"+to_string(line[i])+" from "+format(val)+" to "+format(j)+ ".";
                
                }
            }
        }
    }
    vector<string> path;
    cout<<dist[T]<<"\n";
    for(int i=T; i!=S; i=pre[i]){
        path.push_back(info[i]);
    }
    Rep(i, path.size()-1, 0){
        cout<<path[i]<<"\n";
    }
}
signed main(){
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
// 	n=rd();
    cin>>n;
    memset(h, -1, sizeof h);
	rep(i, 1, n+1){
	   // m=rd();
	    cin>>m;
	    rep(j, 0, m){
	       // stop[i]=rd();
	       cin>>stop[j];
	    }
	    rep(j, 0, m){
	        rep(k, 0, j){
	            int len;
	            // 非环路 长度j-k
	            if(stop[0]!=stop[m-1]){
	                len=j-k;
	            }else{ // 环路 长度为j-k,m-1-j+k最小值
	                len=min(j-k, m-1-j+k);
	            }
	            add(stop[j], stop[k], len, i);
	            add(stop[k], stop[j], len, i);
	        }    
	    }
	}
// 	int k=rd();
    int k;
    cin>>k;
	while(k--){
	   // int S=rd(), T=rd();
	    int S, T;
	    cin>>S>>T;
	    dij(S, T);
	}
	return 0;
}

参考文献

AcWing 1624. 地铁地图(PAT甲级辅导课)y总视频讲解

原创不易
转载请标明出处
如果对你有所帮助 别忘啦点赞支持哈
在这里插入图片描述

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

飞滕人生TYF

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值