• 【JLOI2011】飞行路线


    Alice和Bob现在要乘飞机旅行,他们选择了一家相对便宜的航空公司
    该航空公司一共在n个城市设有业务,设这些城市分别标记为0到n - 1 
    共有m种航线,每种航线连接两个城市,并且航线有一定的价格
    Alice和Bob现在要从一个城市沿着航线到达另一个城市,途中可以进行转机
    航空公司对他们这次旅行也推出优惠,他们可以免费在最多k:种航线上搭乘飞
    那么Alice和Bob这次出行最少花费多少?
    

    还是分层图的套路,有k种航线免费,就建k层,每往下一层就说明免费坐了一次航线
    有一点很重要,分层图的题目空间一定要开够,不要像普通最短路那样看到点数就跑
    还要考虑层数对使用空间的影响
    水题,不多说了

    代码:

    #include<bits/stdc++.h>
    #define N 1500005
    using namespace std;
    
    int n,m,k,s,t,u,v,w;
    
    struct Edge
    {
    	int next,to,dis;
    }edge[N<<1];
    int cnt=1,head[N];
    
    struct Node
    {
    	int u,dis;
    	bool operator < (const Node &a) const
    	{
    		return a.dis<dis;
    	}
    };
    
    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;
    }
    
    int dis[N];
    bool vis[N];
    void Dijkstra(int s)
    {
    	memset(vis,0,sizeof(vis));
    	memset(dis,0x3f,sizeof(dis));
    	priority_queue<Node> q;
    	q.push((Node){s,0});
    	dis[s]=0;
    	while(!q.empty())
    	{
    		int u=q.top().u;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){v,dis[v]});
    			}
    		}
    	}
    }
    
    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;
    }
    
    int main()
    {
    	read(n);read(m);read(k);
    	read(s);read(t);
    	for(register int i=1;i<=m;++i)
    	{
    		read(u);read(v);read(w);
    		for(register int j=0;j<=k;++j)
    		{
    			add_edge(u+j*n,v+j*n,w);
    			add_edge(v+j*n,u+j*n,w);
    		}
    		for(register int j=0;j<k;++j)
    		{
    			add_edge(u+j*n,v+(j+1)*n,0);
    			add_edge(v+j*n,u+(j+1)*n,0);
    		}
    	}
    	for(register int i=0;i<k;++i) add_edge(t+i*n,t+(i+1)*n,0);
    	Dijkstra(s);
    	printf("%d
    ",dis[t+k*n]);
    	return 0;
    }
    
  • 相关阅读:
    android判断程序是否前台显示---及判断屏幕是否是亮的----附赠BAIDU定位的工具类实现代码
    Lock and synchronized 摘自官网, 摘录下来方便笔记
    SQLite 基础
    如何stop,suspend一个线程 在deprecated的情况下
    HashMap 的遍历 for:each 和EntrySet两种方法
    ListView图片异步加载与缓存策略
    android debug学习笔记 monkeyrunner
    回溯法和DFS leetcode Combination Sum
    leetcode Count and Say
    leetcode Jump Game I II 待续 贪心看不懂啊!!!!
  • 原文地址:https://www.cnblogs.com/tqr06/p/11628659.html
Copyright © 2020-2023  润新知