• 赛肯德 | 2017NEERC某题



    我们枚举每一条边的流量x,将它作为底流(也就是比它大的的流量变成差值,比它小的流量为0),然后我们设x就是路径上第K大的那个边的流量。然后跑最短路,加上dis[n]就是当前的答案。然后取min即可。
    算法时间复杂度(O(n^2logn))
    为什么这样子就是最小的呢?????我也很懵逼啊
    因为你考虑ans_x是第K大的流量,设当前处理的为x。
    如果按照上述规定来跑最短路,显然上述所求最短路加上K*ans_x就是答案,而且这个最短路径是一定确定的。下面我们就要求ans_x——如果我们进行遍历然后取min的话,如果保证x!=ans_x的时候不优呢?
    如果x比ans_x小,那么“还有流量”的边一定大于等于K。这样的话最后统计答案最短路会长,x变小——但是变化幅度没有前面的大,所以不优。
    如果x比ans_x大,那么“还有流量”的边一定小于等于K。这样的话最后统计答案最短路会短,x变大——但是变化幅度比前面的大,所以不优。

    代码如下:

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<cmath>
    #include<queue>
    #define MAXN 5010
    using namespace std;
    int n,m,t,k;
    int head[MAXN],done[MAXN];
    long long ans=(long long)1e15;
    long long dis[MAXN];
    vector<int>vec;
    struct Edge{int nxt,to,dis;}edge[MAXN<<1];
    struct Node
    {
        int u;
        long long w;
        friend bool operator < (struct Node x,struct Node y)
            {return x.w>y.w;}
    };
    inline void add(int from,int to,int dis)
    {
        edge[++t].nxt=head[from];
        edge[t].to=to;
        edge[t].dis=dis;
        head[from]=t;
    }
    inline long long dij(int x)
    {
        priority_queue<Node>q;
        for(int i=0;i<=n;i++) dis[i]=(long long)1e15,done[i]=0;
        q.push((Node){1,0}); dis[1]=0; 
        while(!q.empty())
        {
            int u=q.top().u; q.pop();
            if(done[u]) continue;
            done[u]=1;
            for(int i=head[u];i;i=edge[i].nxt)
            {
                int v=edge[i].to;
                long long w=max(edge[i].dis-x,0);
                //printf("v=%d w=%lld %lld
    ",v,w,edge[i].dis);
                if(dis[u]+w<dis[v])
                    dis[v]=dis[u]+w,q.push((Node){v,dis[v]});
            }
        }
        return dis[n];
    }
    int main()
    {
        //freopen("skd.in","r",stdin);
        //freopen("skd.out","w",stdout);
        freopen("ce.in","r",stdin);
        scanf("%d%d%d",&n,&m,&k);
        for(int i=1;i<=m;i++)
        {
            int u,v,w;
            scanf("%d%d%d",&u,&v,&w);
            add(u,v,w),add(v,u,w);
            vec.push_back(w);
        }
        ans=dij(0);
        printf("%lld
    ",ans);
        for(int i=0;i<vec.size();i++)
            ans=min(ans,1ll*vec[i]*k+dij(vec[i])),printf("%lld
    ",ans);
        printf("%lld
    ",ans);
        return 0;
    }
    
  • 相关阅读:
    typescript 箭头表达式
    typescript 参数类型
    ts介绍
    pm2
    koa2安装
    linux 搭建ftp
    CENTOS6.5 安装 mysql5.6 以及搭建双主
    bzoj 3043 (差分序列运用)
    poj 3277 City Horizon
    NOI2015 程序自动分析
  • 原文地址:https://www.cnblogs.com/fengxunling/p/10490520.html
Copyright © 2020-2023  润新知