2.11日考试第一题

题目

众所周知,2018-1-31是个神奇的日子。这天晚上,不仅有百年一遇的蓝月,还有千年一遇的奇观——wyf梦游。

具体地说,wyf梦见自己在一张奇怪的图中。这张图有n个结点,m条带权有向边。此后死,wyf正在结点1,而教室竟然在遥远的结点n!

wyf自然是很害怕迟到的,于是他想知道从1到n的最短路有多长。

他还想知道:(怎么那么多想知道的)若能将任意一条边的边权变为0,从1到n的最短路有多长。

Input

    第一行两个整数n, m代表点数和边数。

    接下来的m行每行输入三个整数,代表一条边的起点,终点和边权。


Output

    输出包含两个整数

    第一个:代表在原图中的最短路长度。

    第二个:代表能够将任意一条边的边权变为0的情况下的最短路长度。

Special Judge

    正确输出第一个答案,获得40%的分数;

    正确输出第二个答案,获得60%的分数;

    如果不知道某个答案,请输出0,至少可以得分。

↑↑↑↑↑题目大概就是这样了,一道非常明显的...呃....最短路问题。在哪里..在那里见过你..听过师兄讲过

就第一步做对最短路长度(邻接表存图),第二步做对第二个问(用队列来做),第三步考虑优化程序(优先队列)

附代码:

#include <bits/stdc++.h>
using namespace std;
const int MAXN = 2e6 + 5;

struct Main {
	struct Vtx {
	    int To;
	    long long Wgt;
	    Vtx *Next;
	
	    Vtx(void) : 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(void) : 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) // i->To
		    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(void)
{
	delete new Main;
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值