CSU 1808 地铁

最短路的变形问题
普通的最短路,选取离出发点最近的一个点对其他的点进行优化
本题则每次选取最短的边作为计算的单位 ,对边的两端点所连接两条边进行优化。
最后在与结点n相连接的边中选择最小的即是答案 

#include<cstdio> 
#include<cstring>
#include<queue>
#include<vector>
#define LL long long
using namespace std;
const int maxn=1e5+7;
const int INF=1e9+7;
int n,m; 
struct Edge{
	int u,v;
	LL c,t;
}edge[maxn];
struct min_edge{
	int lin;
	LL min_length;
	min_edge(int lin,LL min_length):lin(lin),min_length(min_length){} //方便装入队列 
	bool operator<(const min_edge&a)const{  //构造优先队列  此处 >则从小到大排  <则从大到小排 
		return min_length>a.min_length;
	}
};
vector<int>Map[maxn]; //储存与点连接的的边的编号 
int vis[maxn];
LL dis[maxn];
LL jdz(LL a,LL b){
	if(a>b)return a-b;
	else return b-a;
}
int main(){
	while(~scanf("%d%d",&n,&m)){
		for(int i=0;i<=n;i++)Map[i].clear();  
		for(int i=0;i<m;i++)dis[i]=INF;
		memset(vis,0,sizeof(vis));    //初始化 
		
		priority_queue<min_edge>Q;  //最短边 
		for(int i=0;i<m;i++){       //储存边的信息 
			scanf("%d%d%lld%lld",&edge[i].u,&edge[i].v,&edge[i].c,&edge[i].t);
			if(min(edge[i].u,edge[i].v)==1){
				dis[i]=edge[i].t;
				Q.push(min_edge(i,edge[i].t));
			}
			Map[edge[i].u].push_back(i);//储存与点连接的的边的编号 
			Map[edge[i].v].push_back(i);
		}
		
		while(!Q.empty()) {     //dijkstra
			min_edge now=Q.top();Q.pop();
			int x=now.lin;   // 当前最短的边 
			if(vis[x])continue;
			vis[x]=1;
			int L1=edge[x].u,L2=edge[x].v;  //边的两端点
			
			for(int i=0;i<Map[L1].size();i++) { //优化L1端点的边 
				int y=Map[L1][i];
				int time=jdz(edge[x].c,edge[y].c);
				if(dis[y]>dis[x]+time+edge[y].t){
					dis[y]=dis[x]+time+edge[y].t;
					Q.push(min_edge(y,dis[y]));
				}
			}
			for(int i=0;i<Map[L2].size();i++) { //优化L2端点的边 
				int y=Map[L2][i];
				int time=jdz(edge[x].c,edge[y].c);
				if(dis[y]>dis[x]+time+edge[y].t){
					dis[y]=dis[x]+time+edge[y].t;
					Q.push(min_edge(y,dis[y]));
				}
			}
		}
		LL ans=INF;
		for(int i=0;i<Map[n].size();i++) {
			ans=min(ans,dis[Map[n][i]]);
		}
		printf("%lld\n",ans);
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/love_phoebe/article/details/81088884