• 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;
    }
    

    总结

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

  • 相关阅读:
    docker
    redis 3.2.6 on ubuntu 14.04
    go异常处理
    go语言的命令行库
    iptables
    nsq
    etcd-v2第一集
    rabbitmq, windows/linux, c/c++/node.js/golang/dotnet
    zeromq:c,c++,golang及nodejs使用
    golang下的grpc
  • 原文地址:https://www.cnblogs.com/TheShadow/p/11371377.html
Copyright © 2020-2023  润新知