以最低成本在城市中建造街道的算法

Algorithm to build streets in a city with minimum cost?

本文关键字:街道 算法 低成本 城市      更新时间:2023-10-16

问题详情:
拉霍夫是EMLand的市长。EMLand由十字路口和街道组成。从每个十字路口到任何其他十字路口只有一条路径。交集用正交点 1...n 表示。一家建筑公司向拉肖夫提供了重建EMLand的所有街道,但拉肖夫可以选择at most k of them to be rebuilt. 建筑公司为每条街道提供了新的长度,这意味着在街道重建后,街道的长度会发生变化。现在,拉霍夫作为市长必须明智地选择,以尽量减少所有交叉路口之间的路径长度总和。帮助拉肖夫!

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

  1. 计数( C ( 长度将减少的edges(E')数,即 L'

  2. 如果C小于或等于K
            考虑所有边(E'(,即更新E
    中所有此类边的长度


  3.         1 .根据 (L'- L( 按升序
    对所有边 (E'( 进行排序        2 .根据 L' 降序
    对 (L'-L( 相同的边缘(E'' ⊆ E'( 进行排序        3.在 E 中连接 1st K 边(E''' ⊆ E'( 并更新所有此类边的长度

  4. 构造边 E 和长度为 L 的图形 G

  5. 应用任何最短距离算法或 DFS 来查找每对节点的距离黑白。

使用优先级队列和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;
    }

It passes only 2 test cases out of 9 test cases . 为什么这个算法不起作用?
或者应该在这个算法中进行哪些修改才能被接受?参考:
拉肖夫,EMLand市长

  1. 遍历树/图(例如,从任何节点开始的非递归DFS(并计算每条边的使用次数(一侧的节点数*另一侧的节点数(
  2. 对于每个可能的重建,将增量乘以计数
  3. 排序
  4. 利润

请注意,这是一棵树,因此,每条边连接两个连接的组件

假设我们在两个连接的组件 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为正(。