【图】Wander


思路:建带权有向图,再求出单源最短路径
实现:用vtx结构体和grow函数建图,以及它的一个反图(从n到1),再用优先队列查找最短路,最后用同样的方法,用反图求出第二个结果。
代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<cmath>
#include<climits>
#include<vector>
#include<stack>
#include<queue>
using namespace std;
const int MAXN = 2e6 + 5;

struct Main {
	struct Vtx {
		int To;
		long long Wgt;
		Vtx *Next;
		
		Vtx() : Next(NULL) {}
		Vtx(int To, long long Wgt) : 
			To(To), Wgt(Wgt), Next(NULL) {}
	};
	
	struct VtxHead : Vtx {
		Vtx *Head;
		long long Dist;	
		
		void Grow(int To, long long Wgt)
		{
			if (Head) Next = 
				Next->Next = new Vtx(To, Wgt);
			else Head = 
				Next = new Vtx(To, Wgt);
		}
		
		VtxHead() : Head(NULL),
			Dist(LLONG_MAX) {}
	} G[MAXN], AntiG[MAXN];
	
	struct Unit {
		int u;
		long long Dist;
		
		bool operator < (const Unit &x) const
		{
			return Dist > x.Dist;
		}
	};
	
	inline void Search(VtxHead *Graph, int Source)
	{
		priority_queue<Unit> Travel;
		Travel.push( (Unit) { Source, 0 } );
		Graph[Source].Dist = 0;
		
		while (!Travel.empty()) {
			int From = Travel.top().u;
			long long CrtDist = Travel.top().Dist;
			Travel.pop();
			
			if (CrtDist <= Graph[From].Dist)
				for (register Vtx *i = Graph[From].Head;
					i; i = i->Next)
					if (Graph[From].Dist + i->Wgt <
						Graph[i->To].Dist) {
						Graph[i->To].Dist = 
							Graph[From].Dist + i->Wgt;
						
						Travel.push( 
							(Unit) { i->To, Graph[i->To].Dist } );
					}
		}
	}
	
	Main(void)
	{
		int n, m;
		scanf("%d %d", &n, &m);
		
		while (m--) {
			int u, v;
			long long Wgt;
			scanf("%d %d %lld", 
				&u, &v, &Wgt);
				
			G[u].Grow(v, Wgt);
			AntiG[v].Grow(u, Wgt);
		}

		Search(G, 1);
		Search(AntiG, n);
		
		printf("%lld\n", G[n].Dist);
		
		long long MinDist = G[n].Dist;
		for (register int i = 1; i <= n; ++i)
			for (register Vtx *j = G[i].Head;
				j; j = j->Next)
				if (G[i].Dist + AntiG[j->To].Dist <
					MinDist)
					MinDist = 
						G[i].Dist + AntiG[j->To].Dist;
						
		printf("%lld\n", MinDist);
	}
};

int main()
{
	delete new Main;
	
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值