zoukankan      html  css  js  c++  java
  • 【JZOJ5551】【20190625】旅途

    题目

    (n)个点(m)条边的无向图,一条路径的代价定义为路径上前(k)大边的边权和

    对于$k = n o 1 $,求1-n的最短路

    (n,m le 3000 , w_i le 10^9)

    题解

    • 60pts
    • 枚举最小的边(e)将边分为 $ ge e $ 和 $ <e $ ,后者边权设为0,设(dp_{i,j})表示走到(i)(ge e)的边走了(j)条的概率
    • (dp_{n,k})去更新答案,需要预先做一边最短路考虑边数不够的情况
    • 时间复杂度:(O(m^2n log m))
    • 100pts
    • 枚举最小的(e),将每条边的边权设置为(max{0,w - w_e}) ,做Dij,用(dis_{n} + k imes w_e)更新答案
    • 时间复杂度:(O(mn log m))
    #include<bits/stdc++.h>
    #define ll long long
    #define inf 1e18
    
    using namespace std;
    
    const int N=3010;
    int T,n,m,o,hd[N],vis[N],del[N<<1],id[N<<1];
    ll dis[N],ans[N];
    
    struct Edge{int u,v,w,nt;}E[N<<1];
    void adde(int u,int v,int w){
    	E[o]=(Edge){u,v,w,hd[u]};hd[u]=o++;
    	E[o]=(Edge){v,u,w,hd[v]};hd[v]=o++;
    }
    
    bool cmp(int x,int y){return E[x].w==E[y].w?x<y:E[x].w<E[y].w;}
    
    struct data{
    	int u;ll w;
    	data(int _u=0):u(_u){w=dis[u];};
    	bool operator <(const data&A)const{return w>A.w;};
    };
    priority_queue<data>q;
    
    void dijkstra(int e){
    	for(int i=1;i<=n;++i)dis[i]=inf;
    	++T;dis[1]=0;q.push(1);
    	while(!q.empty()){
    		int u=q.top().u;q.pop();
    		if(vis[u]==T)continue;
    		vis[u]=T;
    		for(int i=hd[u];i;i=E[i].nt){
    			int v=E[i].v;
    			if(del[i]){
    				if(dis[v]>dis[u]){
    					dis[v]=dis[u];
    					if(vis[v]!=T)q.push(v);
    				}
    			}else{
    				if(dis[v]>dis[u]+E[i].w-e){
    					dis[v]=dis[u]+E[i].w-e;
    					if(vis[v]!=T)q.push(v);
    				}
    			}
    		}
    	}
    	for(int i=1;i<=n;++i)ans[i]=min(ans[i],dis[n]+1ll*e*i);
    }
    
    int main(){
    	freopen("journey.in","r",stdin);
    	freopen("journey.out","w",stdout);
    	scanf("%d%d",&n,&m);o=1;
    	for(int i=1;i<=m;++i){
    		int u,v,w;
    		scanf("%d%d%d",&u,&v,&w);
    		adde(u,v,w);
    	}
    	for(int i=1;i<o;++i)id[i]=i;
    	sort(id+1,id+o,cmp);
    	for(int i=1;i<=n;++i)ans[i]=inf;
    	dijkstra(0);
    	for(int i=1;i<o;++i){
    		int now=id[i];
    		if(del[now])continue;
    		del[now]=del[now+1]=1;
    		dijkstra(E[now].w);
    	}
    	for(int i=n;i;--i)printf("%lld
    ",ans[i]);
    	return 0;
    }
    
  • 相关阅读:
    面向对象与面向过程
    mul 指令
    Debug 的使用
    子域名扫描器
    div 指令
    C Primer Plus学习笔记(十三)- 结构和其他数据形式
    C Primer Plus学习笔记(十一)- 存储类别、链接和内存管理
    BugkuCTF WEB
    BugkuCTF 逆向
    C Primer Plus学习笔记(十)- 字符串和字符串函数
  • 原文地址:https://www.cnblogs.com/Paul-Guderian/p/11094054.html
Copyright © 2011-2022 走看看