其他分享
首页 > 其他分享> > [JLOI2011]飞行路线题解

[JLOI2011]飞行路线题解

作者:互联网

The Captain

@

目录

题目描述

给定平面上的n个点,定义(x1,y1)到(x2,y2)的费用为min(|x1-x2|,|y1-y2|),求从1号点走到n号点的最小费用。

分析

我们第一时间会想把所有点都连上边,这样在跑一遍dijkstra,不就可以了吗?
但是

对于100%的数据,n<=200000

那我们就想一下如何优化呢
我从样例哪里拿来3个数来看一下

id x y
1 2 2
2 1 1
3 4 5

1到2,需要$min(|X_1-X_2|,|Y_1-Y_2|)=1费用$
1到3,需要$min(|X_1-X_3|,|Y_1-Y_3|)=2费用$
2到3,需要$min(|X_2-X_3|,|Y_2-Y_3|)=3费用$
$1+2=3$难道是巧合?
我们来分析一下

所以我们可以把$X$排序,相邻存边;在把$Y$排序,相邻存边,一共存$4n$条边
这部分的代码我就不放了,到后面去看吧

代码

有点长

#include<bits/stdc++.h>
using namespace std;
int n,d[200010];
struct node
{
	int x,y,id;
}a[200010];
struct edge
{
	int x,s;
	bool operator<(const edge&a)const
    {
        return s>a.s;
    }
};
bool cmpx(node a,node b)
{
	if(a.x==b.x)return a.y<b.y;
	return a.x<b.x;
}
bool cmpy(node a,node b)
{
	if(a.y==b.y)return a.x<b.x;
	return a.y<b.y;
}
int f(node a,node b)
{
	return min(abs(a.x-b.x),abs(a.y-b.y));
}
vector<edge> v[200010];
int main()
{
	cin>>n;
	for(int i=1;i<=n;i++)
	{
		cin>>a[i].x>>a[i].y;
		a[i].id=i;
	}
	sort(a+1,a+n+1,cmpx);
	for(int i=1;i<n;i++)
	{
		v[a[i].id].push_back(edge{a[i+1].id,f(a[i],a[i+1])});
		v[a[i+1].id].push_back(edge{a[i].id,f(a[i],a[i+1])});
	}
	sort(a+1,a+n+1,cmpy);
	for(int i=1;i<n;i++)
	{
		v[a[i].id].push_back(edge{a[i+1].id,f(a[i],a[i+1])});
		v[a[i+1].id].push_back(edge{a[i].id,f(a[i],a[i+1])});
	}
	priority_queue<edge> q;
	q.push(edge{1,0});
	for(int i=2;i<=n;i++)d[i]=1e9;
	while(!q.empty())
	{
		edge x=q.top();
		q.pop();
		if(x.s!=d[x.x])continue;
		for(int i=0;i<v[x.x].size();i++)
		{
			edge y=v[x.x][i];
			if(d[y.x]>d[x.x]+y.s)
			{
				d[y.x]=d[x.x]+y.s;
				q.push(edge{y.x,d[x.x]+y.s});
			}
		}
	}
	cout<<d[n];
}

祝大家AC大吉

标签:node,JLOI2011,min,int,题解,200010,路线,edge,id
来源: https://www.cnblogs.com/gdfzlcx/p/16583467.html