当前位置: 首页 > 知识库问答 >
问题:

以最小成本建造城市街道的算法?

刁星渊
2023-03-14

问题详情:
拉绍夫是埃姆兰市市长。埃姆兰由十字路口和街道组成。从每个交叉口到任何其他交叉口都只有一条路径。交点用正整数1...n表示。一家建筑公司向Rashof提出要重建埃姆兰的所有街道,但Rashof最多可以选择k条进行重建。建筑公司为每条街道提供了一个新的长度,这意味着在街道重建后,街道的长度会发生变化。现在,作为城市的市长,拉绍夫必须明智地做出选择,使所有对交叉口之间的路径长度之和最小化。救救Rashof!

算法:
符号:旧边长为L,新边长为L'和边集E

>

  • 计数(c)长度将减小的边(E')的数目,即L'

    如果C小于或等于K
     、 、 、 、 、 、 、 将所有边(E')考虑在内,即更新E中所有这些边的长度

    其他
           1.基于(L'-L)的所有边(E')按升序排序
             2。根据L'降序排序那些(L'-L)相同的边(E''E')
             3.后K条边(E'''E')并更新E中所有这些边的长度

    构造边为E、长度为L的图G

    应用任何最短距离算法或DFS来寻找每对节点的距离B/W。

    使用优先级队列和Dijkstra算法实现上述算法。

        #include <bits/stdc++.h>
        using namespace std;
        typedef pair<int,int> pii;
        struct s{
        int x;
        int y;
        int a;
        int b;
        int c;
        };
        const int MAX = 100000;
        const long long INF = 100000000000000000;
        vector< pii > G[MAX];
        long long d[MAX];
        void dijkstra(long long start) {
            int u, v, i, c, w;
            priority_queue< pii, vector< pii >, greater< pii > > Q;
            for(i=0;i<MAX;i++){
                d[i]=INF;
            }
            Q.push(pii(0, start));
            d[start] = 0;
            while(!Q.empty()) {
                u = Q.top().second; // node
                c = Q.top().first; // node cost so far
                Q.pop(); // remove the top item.
                if(d[u] < c) continue;
                for(i = 0; i < G[u].size(); i++) {
                    v = G[u][i].first; // node
                    w = G[u][i].second; // edge weight
                    if(d[v] > d[u] + w) {
                        d[v] = d[u] + w;
                        //cout<<d[v];
                        Q.push(pii(d[v], v));
                    }
                }
            }
        }
        bool func(const s s1,const s s2) { return (s1.c < s2.c); }
        bool func2(const s s1,const s s2) { return (s1.b < s2.b); }
        int main() {
            long long n, e, u, V, w,x,y,a,b,t,i,j,k,res,z=2;
            s S;
            vector<s> v;
            map<pair<int,int>,int> m;
            map<pair<int,int>,int>::iterator it;
            cin>>t;
            while(t--){
                cin>>n>>k;
                for(i = 1; i <= n; i++) G[i].clear();
                v.clear();
                m.clear();
                for(i=1;i<n;i++){
                    cin>>x>>y>>a>>b;
                    if(b<a){
                        S.x = x;
                        S.y =y;
                        S.a=a;
                        S.b=b;
                        S.c=b-a;
                        v.push_back(S);
                    }
                    m[make_pair(x,y)]=a;
                }
                if(v.size()<=k){
                    for(i=0;i<v.size();i++){
                         m[make_pair(v[i].x,v[i].y)]=v[i].b;
                    }
                    it = m.begin();
                    for(;it!=m.end();++it){
                        u = it->first.first;
                        V = it->first.second;
                        w = it->second;
                        G[u].push_back(pii(V, w));
                        G[V].push_back(pii(u, w));
                    }
                    res = 0;
                    for(i=1;i<=n;i++){
                        dijkstra(i);
                        for(j= 1; j <= n; j++) {
                            if(i == j) continue;
                            if(d[j] >= INF) ;
                            else res+=d[j];
                        }
                    }
                    cout<<res/z<<"\n";
                }
                else{
                    sort(v.begin(),v.end(),func);
                    for(i=0;i<v.size();i++){
                        j = i;
                        while(v[i].c==v[j].c&&j<v.size())j++;
                        sort(v.begin()+i,v.begin()+j,func2);
                        i=j;
                    }
                    for(i=0;i<k;i++){
                         m[make_pair(v[i].x,v[i].y)]=v[i].b;
                    }
                    it = m.begin();
                    for(;it!=m.end();++it){
                        u = it->first.first;
                        V = it->first.second;
                        w = it->second;
                        G[u].push_back(pii(V, w));
                        G[V].push_back(pii(u, w));
                    }
                    res = 0;
                    for(i=1;i<=n;i++){
                        dijkstra(i);
                        for(j= 1; j <= n; j++) {
                            if(i == j) continue;
                            if(d[j] >= INF) ;
                            else res+=d[j];
                        }
                    }
                    cout<<res/z<<"\n";
                }
            }
            return 0;
        }
    
  • 共有1个答案

    宗乐池
    2023-03-14

    注意,这是一棵树,所以,每条边连接两个相连的组件。

    假设我们在两个连通分量A和B之间有边连通,其中包含n和m个交点,因此,通过减小边的x个单位,我们将减小总距离n*m*x

    A---B---C----E
        |   |
        |   |
    D----   -----F
    

    看上图,B和C之间的边连接两个连通的分量(A,B,D)和(C,E,F),减小这条边的权值将减小(A,B,D)和(C,E,F)之间的距离

    因此,算法是选择k条边,该边具有最大的n*m*x(如果x为正)。

     类似资料:
    • 河的两边有相等数量的城市。从一侧的城市到另一侧的城市的桥由表示,其中城市1在下侧,桥到城市3在上侧。我们必须找到最大数量的非重叠桥。因此对于输入的输出将是,因为是不重叠的。 这是我的密码- 对此有没有更优化的算法?

    • 问题内容: 我正在尝试从Google json获取$ street,$ city和$ country字符串。它适用于我的家庭住址:http : //maps.googleapis.com/maps/api/geocode/json?latlng=52.108662,6.307370&sensor=true 但是,对于像这样的示例中数组中包含更多数据的其他地址:http : //maps.googl

    • 我的城市是一款增量点击游戏。你需要点击收获原始资源,然后注意: 要用现金购买东西 研究需要脑力 运行事物需要能量 矿石可提供基础材料 水可作为消耗品 犯罪会让你付出代价...(尚未实施) 污染会使你生病    

    • 问题内容: 在我当前的android应用程序中,我想根据输入的城市名称,街道名称或邮政编码获取地理坐标。我该怎么做? 最好的问候,罗尼 问题答案: 查看方法。 像这样使用它:

    • 定义 选择城市的组件。 图片展示 代码演示 import City from 'pile/dist/components/city' <City show={false} // cityArr={cityArr} // 城市数组 // position= {cityArr[0]} //定位城市 // 城市对象的默认属性为 // city_id、city_name、firs

    • 提示 页面模板源码免费开源,在uni-app的插件市场uView的 示例项目 中,在右上角选择"使用 HBuilderX 导入示例项目" 或者 "下载示例项目ZIP", 在HX运行项目即可看到和使用模板。 这个界面功能,为城市选择示例,此仅为参考模板,如果演示达不到您想要的效果,请自行修改即可。