csu 1808 地铁 拆点最短路

本文介绍了一种针对地铁网络的路径规划算法实现。该算法通过拆分地铁站点并重新构建图结构来解决最短路径问题。具体步骤包括为每条地铁线路创建节点、连接边,并按线路编号顺序连接同一站点内的节点,最终运用Dijkstra算法找出从起点到终点的最短路径。
摘要由CSDN通过智能技术生成

对于每一条不同的地铁线路进行拆点,生成新的节点,连边,然后对于同一地铁站内的不同节点按照他们所属的地铁线的编号从小到大连接,最后跑最短路,建图是难点,我们可以对同一地铁线的不同边进行统一处理,同时再依次添加到相应的地站的集合中,因为是顺序插入,所以本身就是从小到大的了,具体见代码。

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <vector>
#include <map>
#include <cmath>
#include <set>
#include <queue>
using namespace std;

const int INF=1e9+10;
const double EPS = 1e-10;  
typedef unsigned long long ll;
const int mod=1e9+7;
typedef pair<ll,int> P;


int n,m,tot;
vector<pair<int,int> >st[100005];
struct edge1{
	int u,v,w;
};
vector<edge1> line[100005];
ll linf=(1LL<<63)-1;

ll d[200005];
struct edge{
	int v,w;
};
vector<edge> g[200005];

void add_edge(int u,int v,int w){
	g[u].push_back((edge){v,w});
	g[v].push_back((edge){u,w});
}
void dijkstra(){
	for(int i=0;i<tot;i++)
		d[i]=linf;
	priority_queue<P,vector<P>,greater<P> >que;
/*	d[s]=0;
	que.push(P(0,s));*/
	for(int i=0;i<st[1].size();i++){
		int u=st[1][i].first;
		d[u]=0;
		que.push(P(0,u));
	}
	while(!que.empty()){
		P p=que.top(); que.pop();
		int v=p.second;
		if(d[v]<p.first) continue;
		//printf("11   %d  %d  %d\n",p.first,v,g[v].size() );
		for(int i=0;i<g[v].size();i++){
			edge e=g[v][i];
			//printf("222  %d  %d\n",e.v,e.w );
			if(d[e.v]>d[v]+e.w){
				d[e.v]=1LL*d[v]+e.w;
				que.push(P(d[e.v],e.v));
			}
		}
	}
	//return d[cnt];
}

void init(){
	for(int i=0;i<=n;i++)
		line[i].clear(),st[i].clear();
}
int main(){
	//freopen("out.txt","w",stdout);
	while(scanf("%d %d",&n,&m)!=EOF){
		//printf("m  %d   n  %d\n",m,n );
		for(int i=0;i<m;i++){
			int u,v,l,w;
			scanf("%d %d %d %d",&u,&v,&l,&w);
			line[l].push_back((edge1){u,v,w});
		}
		tot=0;
		for(int i=1;i<=n;i++){
			for(int j=0;j<line[i].size();j++){
				//printf("%d    %d\n",i,j );
				int u=line[i][j].u,v=line[i][j].v,w=line[i][j].w;
				if(!st[u].size()||st[u].back().second!=i){
					st[u].push_back(make_pair(tot++,i));
				}
				if(!st[v].size()||st[v].back().second!=i){
					st[v].push_back(make_pair(tot++,i));
				}
				add_edge(st[u].back().first,st[v].back().first,w);		
			}
		}
		for(int i=1;i<=n;i++){
			for(int j=1;j<st[i].size();j++){
				int u=st[i][j-1].first,v=st[i][j].first;
				int w=st[i][j].second-st[i][j-1].second;
				add_edge(u,v,w);
			}
		}
		ll ans=linf;
		dijkstra();
		for(int i=0;i<st[n].size();i++){
			int u=st[n][i].first;
			ans=min(ans,d[u]);
		}
		for(int i=0;i<tot;i++)
			g[i].clear();
		init();
		printf("%lld\n",ans);
	}
    return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值