zoukankan      html  css  js  c++  java
  • [CF1433G] Reducing Delivery Cost

    Description

    给定一张图 ((n le 1000, m le 1000)),图上有 (k) 对点 ((a_i,b_i)) 表示有一个运输项目从 (a_i) 运输到 (b_i)。现在你可以选择一条边将它的权值变为零,要求最小化所有运输项目的最短距离的和。

    Solution

    考虑将每条边 (e(u,v)) 的权值变为 (0) 对结果的影响,对于运输计划 ((a,b)),其若不经过 ((u,v)) 则为其原答案,要么经过 ((u,v)) 则答案为 (min(d_{a,u}+d_{v,b}, d_{a,v}+d_{u,b})),二者取最小值即可。

    于是我们只需要预处理出所有点对之间的最短路,然后模拟上述过程即可。求所有点对最短路的过程可以用 Dijkstra 做到 (O(nm log n))

    #include <bits/stdc++.h>
    using namespace std;
    const int N = 1005;
    #define reset(x) memset(x,0,sizeof x)
    #define reset3f(x) memset(x,0x3f,sizeof x)
    namespace sp {
    vector<pair<int,int> > g[N];
    int n,v0=1,d[N],v[N];
    void make(int t1,int t2,int t3) {
        g[t1].push_back(make_pair(t2,t3));
    }
    void reset_graph() {
        for(int i=0;i<=n;i++) g[i].clear();
    }
    void solve() {
        priority_queue<pair<int,int> > qu;
        reset3f(d);reset(v);
        d[v0]=0;
        qu.push(make_pair(0,v0));
        while(qu.size()) {
            int p=qu.top().second,r=qu.top().first;
            qu.pop();
            if(r+d[p]) continue;
            for(int i=0;i<g[p].size();i++) {
                int q=g[p][i].first,w=g[p][i].second;
                if(d[q]>d[p]+w) {
                    d[q]=d[p]+w;
                    qu.push(make_pair(-d[q],q));
                }
            }
        }
    }
    }
    
    struct edge {int u,v,w;} ed[N];
    int n,m,k,t1,t2,t3,a[N],b[N],d[N][N];
    
    void readdata()
    {
        cin>>n>>m>>k;
        for(int i=1;i<=m;i++)
        {
            cin>>t1>>t2>>t3;
            sp::make(t1,t2,t3);
            sp::make(t2,t1,t3);
            ed[i]={t1,t2,t3};
        }
        for(int i=1;i<=k;i++)
        {
            cin>>a[i]>>b[i];
        }
    }
    void presolve()
    {
        for(int i=1;i<=n;i++)
        {
            sp::v0=i;
            sp::solve();
            for(int j=1;j<=n;j++) d[i][j]=sp::d[j];
        }
    }
    void solve()
    {
        int ans=1e18;
        for(int i=1;i<=m;i++)
        {
            int u=ed[i].u,v=ed[i].v,w=ed[i].w;
            int tans=0;
            for(int j=1;j<=k;j++)
            {
                tans+=min(d[a[j]][b[j]],min(d[a[j]][u]+d[v][b[j]], d[a[j]][v]+d[u][b[j]]));
            }
            ans=min(ans,tans);
        }
        cout<<ans<<endl;
    }
    
    signed main()
    {
        readdata();
        presolve();
        solve();
        return 0;
    }
    
  • 相关阅读:
    运行时动态的创建form的方法
    用X++代码来动态的改变表的属性
    使用WinAPI类来查找文件
    用循环得到表中所有的字段
    用X++建立和调用报表(Report)
    JAVA 保留字
    Cygwin使用
    系统程序员成长计划-算法与容器(三) (上)
    系统程序员成长计划工程管理(二)
    系统程序员成长计划-算法与容器(三) (下)
  • 原文地址:https://www.cnblogs.com/mollnn/p/13860302.html
Copyright © 2011-2022 走看看