zoukankan      html  css  js  c++  java
  • 【SHOI2012】回家的路

    2046年OI城的城市轨道交通建设终于全部竣工,由于前期规划周密,建成后的轨道交通网络由2n条地铁
    线路构成,组成了一个n纵n横的交通网。如下图所示,这2n条线路每条线路都包含n个车站,而每个车站
    都在一组纵横线路的交汇处。
    出于建设成本的考虑,并非每个车站都能够进行站内换乘,能够进行站内换乘的地铁站共有m个,在下图
    中,标上方块标记的车站为换乘车站。已知地铁运行1站需要2分钟,而站内换乘需要步行1分钟。
    Serenade想要知道,在不中途出站的前提下,他从学校回家最快需要多少时间(等车时间忽略不计)
    

    经典的分层图,把路径分为横向路径和纵向路径
    首先按照横坐标排序,依次判断每个点的横坐标是否相同
    如果相同,就连一条双向边,权值为两点纵坐标之差的两倍
    同理,再按纵坐标排序,连边

    这样就处理好了只横向走和只纵向走的路径,
    接下来在两层中表示同一个点的位置连一条权值为1的边
    表示在这里可以花费1的价值转向

    然后跑最短路即可

    #include <bits/stdc++.h>
    #define N 400005
    #define M 2000005
    using namespace std;
    
    int n,m,S,T;
    
    struct Edge
    {
    	int next,to,dis;
    }edge[M];
    int cnt=0,head[N];
    
    template<class T>inline void read(T &res)
    {
    	char c;T flag=1;
    	while((c=getchar())<'0'||c>'9')if(c=='-')flag=-1;res=c-'0';
    	while((c=getchar())>='0'&&c<='9')res=res*10+c-'0';res*=flag;
    }
    
    struct Road
    {
    	int x,y,id;
    } a[N];
    
    struct Node
    {
    	int v,id;
    	inline friend bool operator<(Node x, Node y) {return x.v>y.v;}
    };
    
    inline void add_edge(int from,int to,int dis)
    {
    	edge[++cnt].next=head[from];
    	edge[cnt].to=to;
    	edge[cnt].dis=dis;
    	head[from]=cnt;
    }
    
    inline bool cmp1(Road a,Road b) {return a.x==b.x?a.y<b.y:a.x<b.x;}
    
    inline bool cmp2(Road a,Road b) {return a.y==b.y?a.x<b.x:a.y<b.y;}
    
    int dis[N+5];
    bool vis[N+5];
    inline void dijkstra(int u)
    {
    	priority_queue<Node> q;
    	memset(dis,0x3f,sizeof(dis));
    	dis[u]=0;
    	q.push((Node){0,u});
    	while(!q.empty())
    	{
    		int u=q.top().id;
    		q.pop();
    		if(vis[u]) continue;
    		vis[u]=1;
    		for(register int i=head[u];i;i=edge[i].next)
    		{
    			int v=edge[i].to;
    			if(dis[v]>dis[u]+edge[i].dis)
    			{
    				dis[v]=dis[u]+edge[i].dis;
    				if(!vis[v]) q.push((Node){dis[v],v});
    			}
    		}
    	}
    }
    
    int main()
    {
    	read(n);read(m);
    	n=m+2;
    	S=n-1;
    	T=n;
    	for(register int i=1;i<=n;++i)
    	{
    		read(a[i].x);
    		read(a[i].y);
    		a[i].id=i;
    	}
    	sort(a+1,a+n+1,cmp1);
    	for(register int i=1;i<n;++i)
    	{
    		if(a[i].x==a[i+1].x)
    		{
    			add_edge(a[i].id,a[i+1].id,(a[i+1].y-a[i].y)<<1);
    			add_edge(a[i+1].id,a[i].id,(a[i+1].y-a[i].y)<<1);
    		}
    	}
    	sort(a+1,a+n+1,cmp2);
    	for(register int i=1;i<n;++i)
    	{
    		if(a[i].y==a[i+1].y)
    		{
    			add_edge(a[i].id+n,a[i+ 1].id+n,(a[i+1].x-a[i].x)<<1);
    			add_edge(a[i+1].id+n,a[i].id+n,(a[i+1].x-a[i].x)<<1);
    		}
    	}
    	for(register int i=1;i<=n-2;++i)
    	{
    		add_edge(i,i+n,1);
    		add_edge(i+n,i,1);
    	}
    	add_edge(S,S+n,0);
    	add_edge(S+n,S,0);
    	add_edge(T,T+n,0);
    	add_edge(T+n,T,0);
    	dijkstra(S);
    	printf(dis[T]==0x3f3f3f3f?"-1
    ":"%d
    ",dis[T]);
    	return 0;
    }
    
  • 相关阅读:
    C#for循环——迭代法、穷举法
    C#循环语句
    C#算数运算符、关系运算符、逻辑运算符、语句
    C#visual2012基本操作、数据类型、类型转换
    C#进制转化
    Ajax用法
    《四》JAVA 字符输入输出流
    《三》Java IO 字节输入输出流
    《二》Java IO 流的分类介绍
    《一》File 类的介绍
  • 原文地址:https://www.cnblogs.com/tqr06/p/11625928.html
Copyright © 2011-2022 走看看