• Luogu P4568 [JLOI2011]飞行路线 题解


    闲扯

    听说这题是分层图板子题??

    蒟蒻表示没学过啊,但是感觉直接拆点就可以了啊 (qwq)

    不是和 (NOI2019 D1 T1) 一毛一样吗(雾)其实是由于那道题数据过水

    Solution

    光看题面,已经很明确的说明了要求最短路,但是有一个附加条件,可以有 (k) 次乘坐航班不要钱这种好事我咋遇不到呢

    再看数据范围, (N) 很小,只有 (10^4) ; (k) 也很小,只有 (10)

    看到这里,应该就很清晰了,我们把每一个点拆开,拆成 (11) 个点,分别表示免费乘坐了 (0dots k) 次,到这个点的最小距离。一共有 (10^5) 个点,是一个十分正常的最短路的数据范围这个看着舒服多了

    然后考虑转移。

    对于第 (i) 个城市,免费乘坐 (j) 次的最短距离 (dis_{i,j}=Min(Min(dis_{u,j-1}),Min(dis_u,j+w_{u,i}))) 。(其中 (u!=i) )

    然后我们就可以愉快的跑 (Dijkstra) 了。

    不过在堆优化用到的结构体里面,要多加一个 (st) 表示已经坐了 (st) 次不要钱的航班了。

    Code

    #include<bits/stdc++.h>
    #define del(a,i) memset(a,i,sizeof(a))
    #define ll long long
    #define inl inline
    #define il inl void
    #define it inl int
    #define ill inl ll
    #define re register
    #define ri re int
    #define rl re ll
    #define mid ((l+r)>>1)
    #define lowbit(x) (x&(-x))
    #define INF 0x3f3f3f3f
    using namespace std;
    template<class T>il read(T &x){
    	int f=1;char k=getchar();x=0;
    	for(;k>'9'||k<'0';k=getchar()) if(k=='-') f=-1;
    	for(;k>='0'&&k<='9';k=getchar()) x=(x<<3)+(x<<1)+k-'0';
    	x*=f;
    }
    template<class T>il print(T x){
    	if(x/10) print(x/10);
    	putchar(x%10+'0');
    }
    ll mul(ll a,ll b,ll mod){long double c=1.;return (a*b-(ll)(c*a*b/mod)*mod)%mod;}
    it qpow(int x,int m,int mod){
    	int res=1,bas=x%mod;
    	while(m){
    		if(m&1) res=(res*bas)%mod;
    		bas=(bas*bas)%mod,m>>=1;
    	}
    	return res%mod;
    }
    const int MAXN = 1e4+5;
    int n,m,k,s,t,u,v,d,dis[11][MAXN],ans=INF,head[MAXN],num_edge;
    struct Edge{
    	int next,to,dis;
    	Edge(){}
    	Edge(int next,int to,int dis):next(next),to(to),dis(dis){}
    }edge[MAXN*10];
    il add_edge(int u,int v,int dis){
    	edge[++num_edge]=Edge(head[u],v,dis),head[u]=num_edge;
    	edge[++num_edge]=Edge(head[v],u,dis),head[v]=num_edge;
    }
    struct Node{
    	int pos,dis,st;
    	Node(){}
    	Node(int pos,int dis,int st):pos(pos),dis(dis),st(st){}
    	bool operator <(const Node &t) const{
    		return dis>t.dis;
    	}
    };
    bool tr[11][MAXN];
    il dijkstra(int s){
    	del(dis,0x3f),dis[0][s]=0;
    	priority_queue<Node> q;q.push(Node(s,0,0));
    	while(!q.empty()){
    		Node tmp=q.top();q.pop();
    		ri pos=tmp.pos,st=tmp.st;
    		if(tr[st][pos]) continue;
    		tr[st][pos]=1;
    		for(ri i=head[pos];i;i=edge[i].next){
    			if(dis[st][edge[i].to]>dis[st][pos]+edge[i].dis){
    				dis[st][edge[i].to]=dis[st][pos]+edge[i].dis;
    				if(!tr[st][edge[i].to]) q.push(Node(edge[i].to,dis[st][edge[i].to],st));
    			}
    			if(st+1<=k&&dis[st+1][edge[i].to]>dis[st][pos]){
    				dis[st+1][edge[i].to]=dis[st][pos];
    				if(!tr[st+1][edge[i].to]) q.push(Node(edge[i].to,dis[st+1][edge[i].to],st+1));
    			}
    		}
    	}
    }
    int main()
    {
    //	freopen(".in","r",stdin);
    //	freopen(".out","w",stdout);
    	read(n),read(m),read(k),read(s),read(t),++s,++t;
    	for(ri i=1;i<=m;++i) read(u),read(v),read(d),add_edge(++u,++v,d);
    	dijkstra(s);
    	for(ri i=0;i<=k;++i) ans=min(ans,dis[i][t]);
    	printf("%d",ans);
    	return 0;
    }
    

    总结

    这种题一般都是一个套路问题,多做做题,就可以熟练掌握了呢~~

  • 相关阅读:
    [PCB设计] 1、硬件原理图设计规范(一)——基本原则
    [每日电路图] 8、三轴加速度计LIS3DH电路图及功耗等指标
    [安卓] 19、一个蓝牙4.0安卓DEMO
    [异常解决] MPU6050启动异常读出陀螺仪和加速度计的值全为0的解决办法
    [异常解决] android studio检测不到手机的解决办法——ADB驱动自己安装
    [每日电路图] 7、设计一个PCB的流程及细节·总结——给外行的同学或刚入行的同学一个宏观鸟瞰电路板设计的大致流程的文章
    [专业名词·硬件] 2、DCDC、LDO电源稳压基本常识(包含基本原理、高效率模块设计、常见问题、基于nRF51822电源管理模块分析等)·长文
    mysql获取某个字段平均值方法AVG函数的使用
    Linux设置SSH隧道连接
    docker入门实例(转载)
  • 原文地址:https://www.cnblogs.com/TheShadow/p/11371377.html
Copyright © 2020-2023  润新知