zoukankan      html  css  js  c++  java
  • 【洛谷6961】[NEERC2017] Journey from Petersburg to Moscow(三分+最短路)

    点此看题面

    • 给定一张(n)个点(m)条边的无向图,定义一条路径的长度为其中前(k)大的边权之和。
    • 求从(1)(n)的最短路。
    • (n,mle3000)

    枚举第(k)大+最短路

    考虑枚举第(k)大的权值(v),然后将所有边权减去(v)(原本小于(v)的设为(0))。

    接着只需很普通地跑遍最短路,加上(k imes v)更新答案即可。

    关于正确性,对于一条路径,设这个边权是第(k')大的:

    • 如果(k'<k),那么排名(k'+1sim k)的边权都被视作(v)更新答案,肯定不优。
    • 如果(k'>k),那么排名(k+1sim k')的边权(w)也都对答案产生了(w-v)的额外贡献,肯定不优。

    因此每条路径确实只会在枚举到它的第(k)大权值时取到最优答案,正确性得证。

    三分优化

    实际上这个第(k)大权值(v)是可以三分的,这样一来就能做到更优的复杂度。

    代码:(O(nlognlogm))

    #include<bits/stdc++.h>
    #define Tp template<typename Ty>
    #define Ts template<typename Ty,typename... Ar>
    #define Reg register
    #define RI Reg int
    #define Con const
    #define CI Con int&
    #define I inline
    #define W while
    #define N 3000
    #define LL long long
    #define add(x,y,z) (e[++ee].nxt=lnk[x],e[lnk[x]=ee].to=y,e[ee].v=z)
    using namespace std;
    int n,m,k,ee,lnk[N+5],ev[N+5];struct edge {int to,nxt,v;}e[2*N+5];
    typedef pair<LL,int> Pr;priority_queue<Pr,vector<Pr>,greater<Pr> > q;
    int vis[N+5];LL dis[N+5];I LL Dij(CI v)//最短路
    {
    	RI i,k;for(i=1;i<=n;++i) dis[i]=1e18,vis[i]=0;q.push(make_pair(dis[1]=0,1));
    	W(!q.empty()) if(k=q.top().second,q.pop(),!vis[k]) for(vis[k]=1,i=lnk[k];i;i=e[i].nxt)
    		dis[k]+max(e[i].v-v,0)<dis[e[i].to]&&(q.push(make_pair(dis[e[i].to]=dis[k]+max(e[i].v-v,0),e[i].to)),0);//边权减v
    	return dis[n];
    }
    int main()
    {
    	RI i,x,y,z;for(scanf("%d%d%d",&n,&m,&k),i=1;i<=m;++i) scanf("%d%d%d",&x,&y,&z),add(x,y,z),add(y,x,z),ev[i]=z;
    	RI l=0,r,m1,m2;sort(ev+1,ev+m+1),r=unique(ev+1,ev+m+1)-ev-1;//排序去重
    	#define Calc(i) (Dij(ev[i])+1LL*k*ev[i])//最短路+k*第k大
    	W(r-l>2) m1=l+(r-l)/3,m2=m1+(r-l)/3,Calc(m1)<Calc(m2)?r=m2:l=m1;//三分答案
    	LL t=1e18;for(i=l;i<=r;++i) t=min(t,Calc(i));return printf("%lld
    ",t),0;
    }
    
    败得义无反顾,弱得一无是处
  • 相关阅读:
    VFL语言简洁
    TETeLasr Cutting System 开机回零问题
    TETELaser Cutting System 不连续吹起的问题
    C语言 printf 格式化输出函数
    kbhit()
    电子齿轮 电子凸轮
    memset
    .h(头文件) .lib(库文件) .dll(动态链接库文件) 之间的关系和作用的区分
    pdf点击超链接后返回:alt+ 向左 /向右
    关于 char 、 wchar_t 、 TCHAR 、 _T() ||| 宏 _T 、 TEXT 、 _TEXT 、 L
  • 原文地址:https://www.cnblogs.com/chenxiaoran666/p/Luogu6961.html
Copyright © 2011-2022 走看看