zoukankan      html  css  js  c++  java
  • 【NOIP模拟】距离

    题面

    对梦想的持续追求让实力本身很弱的David一天天变强。
    他最终考上了自己所喜欢的大学。
    北京有啥好大学想必大家都比我清楚吧。

    成都到北京之间有 座城市,城市和城市之间由 条双向通行的道路相连,城市和城市之间两两可达。通过第条道路需要交纳 的过路费。Acid公司很喜欢有梦想的年轻人,他们决定对前往高校上学的学生的路费予以补助。补助的方式是,在一条路径

    上,你只需要交纳路费最贵的前 条道路的费用就可以了。

    如果路径经过了小于 条道路则不补助(这么近你自己给嘛~)你的任务是求出David到达梦想中的学校所需要的最小路费。

    分析

    因为昨晚上才做了一个二分的题,因此拿着就开始二分,然后又是染0和1。。好吧挂得只有15分。。。

    就像出题人所言,你看这数据范围如此小,怎么会是二分呢??二分的题的n怎么也是跟了4个0的吧??

    正确姿势

    枚举答案中最大的不收费边设其价值为valx,然后把所有的边的边权减去valx,不足 valx的设为0,跑最短路,最后把答案加上k*valx ,然后再对所有的情况取min就是最优解

    我们设最短路径中有x条边大于k

    当 x取到k的时候,答案是正确的。刚好k条边收了费。

    而如果最短路径中有大于k条边是正数,我们将从大到小的第y条边的边权作为新的valx,并令其为valy

    设原先的最短路为 M,以 valy作为答案,求出的答案将会变为 M-(valy-valx)*x+valy*k这个答案是比M+valx*k小的

    证明很简单,抓住valy>valx,x>k,即可,不再赘述。

    代码

    #include<bits/stdc++.h>
    using namespace std;
    #define N 3030
    #define mp make_pair
    #define ll long long
    #define INF 0x7fffffff7fffffff
    typedef pair<ll,ll> pii;
    ll n,m,k,cnt,ans=INF;
    ll vis[N],d[N],first[N];
    struct email
    {
        ll u,v,w,o;
        ll nxt;
    }e[N*4];
    
    inline void add(ll u,ll v,ll o)
    {
        e[++cnt].nxt=first[u];first[u]=cnt;
        e[cnt].u=u;e[cnt].v=v;e[cnt].o=o;
    }
    priority_queue<pii>q;
    ll get()
    {
        memset(d,0x3f,sizeof(d));
        memset(vis,0,sizeof(vis));
        while(!q.empty())q.pop();
        d[1]=0;    q.push(mp(-d[1],1));
        while(!q.empty())
        {
            pii x=q.top();q.pop();
            ll u=x.second;
            if(vis[u])continue;vis[u]=1;
            for(ll i=first[u];i;i=e[i].nxt)
            {
                ll v=e[i].v,w=e[i].w;
                if(d[v]>d[u]+w&&d[u]+w<ans)
                    d[v]=d[u]+w,q.push(mp(-d[v],v));
            }
        }
        return d[n];
    }
    
    int main()
    {
        scanf("%lld%lld%lld",&n,&m,&k);
           for(ll i=1;i<=m;i++)
        {
            ll u,v,o;
               scanf("%lld%lld%lld",&u,&v,&o);
            add(u,v,o);add(v,u,o);
           }
           for(ll i=0;i<=cnt;i++)
           {
               ll del=e[i].o;
               for(ll j=1;j<=cnt;j++)e[j].w=max((ll)0,e[j].o-del);
               ans=min(ans,get()+k*del);
           }
        printf("%lld
    ",ans);
        return 0;
    }
  • 相关阅读:
    比赛-ZR DAY1 (04 Aug, 2018)
    Java NIO系列教程(十一) Pipe
    Java NIO系列教程(九) ServerSocketChannel
    Java NIO系列教程(十) Java NIO DatagramChannel
    Java NIO系列教程(七) FileChannel
    Java NIO系列教程(八) SocketChannel
    Java NIO系列教程(六) Selector
    Java NIO系列教程(四) Scatter/Gather
    Java NIO系列教程(五) 通道之间的数据传输
    Java NIO系列教程(二) Channel
  • 原文地址:https://www.cnblogs.com/NSD-email0820/p/9888321.html
Copyright © 2011-2022 走看看