• 分层图最短路


    思想和应用

    当遇到一些需要对边权进行操作的题目时,我们可以建立一些分层图,分别对边权进行修改然后再跑最短路等等来解决问题

    例题:Luogu P4568

    思路

    完全是一个裸题,由于(k)的范围较少,所以可以建出(k+1)个分层图,分别代表将(0)条,(1)条......(k)条边的边权变为(0)。然后再跑一遍(Dijkstra),总时间复杂度为(O(k*(mlog_2m)))

    Code

    #include<iostream>
    #include<algorithm>
    #include<cstdio>
    #include<cmath>
    #include<cstring>
    #include<queue>
    #define ll long long
    using namespace std;
    const int N=10005,M=100005;
    int n,m,k,s,t,tot,ans=2147483647;
    int head[N*22],edge[M*22],Nxt[M*22],ver[M*22],d[N*22];
    bool v[N*22];
    priority_queue < pair <int,int> > q;
    void add(int x,int y,int z){
    	ver[++tot]=y;
    	edge[tot]=z;
    	Nxt[tot]=head[x];
    	head[x]=tot;
    }
    void dijkstra(int ss){
    	for(int i=0;i<=N*20;i++){
    		d[i]=2147483647;
    	}
    	d[ss]=0;
    	q.push(make_pair(0,ss));
    	while(!q.empty()){
    		int x=q.top().second;
    		q.pop();
    		if(v[x]) continue;
    		v[x]=1;
    		for(int i=head[x];i;i=Nxt[i]){
    			int y=ver[i],z=edge[i];
    			if(d[y]>d[x]+z){
    				d[y]=d[x]+z;
    				q.push(make_pair(-d[y],y));
    			}
    		}
    	}
    }
    int main()
    {
    	scanf("%d%d%d",&n,&m,&k);
    	scanf("%d%d",&s,&t);
    	s++,t++;
    	for(int i=1,x,y,z;i<=m;i++){
    		scanf("%d%d%d",&x,&y,&z);
    		x++,y++;
    		add(x,y,z);
    		add(y,x,z);
    		for(int j=1;j<=k;j++){
    			add(x+j*n,y+j*n,z);
    			add(y+j*n,x+j*n,z);//每一层上单独建图
    			add(x+(j-1)*n,y+j*n,0);
    			add(y+(j-1)*n,x+j*n,0);//层与层之间
    		}
    	}
    	dijkstra(s);
    	for(int i=0;i<=k;i++){
    		ans=min(ans,d[i*n+t]);//每一层的终点都有可能成为最终的答案
    	}
    	printf("%d
    ",ans);
    	return 0;
    }
    
  • 相关阅读:
    windows7管理员权限
    Linux编程 第一个Hello World的C程序
    初步接触XCode和IPhone Simulator
    Android调用WCF
    mysql常用命令
    怎样利用Python制作守护进程
    Android模拟器如何设置DNS访问局域网内网站
    ubuntu下mysql攻略
    IIS7快速启动
    内存出错有时候是free后没有给指针赋NULL
  • 原文地址:https://www.cnblogs.com/57xmz/p/14416294.html
Copyright © 2020-2023  润新知