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

时间:2014-12-22 06:48:14

标签: c++ algorithm graph shortest-path

问题详情:
Rashof是EMLand的市长。 EMLand由交叉路口和街道组成。从每个交叉口到任何其他交叉口只有一条路径。交叉点由正整数1 ... n表示。 一家建筑公司已经提供Rashof重建EMLand的所有街道,但Rashof可以选择at most k of them to be rebuilt.建筑公司为每条街道提供了一个新的长度,这意味着在街道重建之后,街道的长度会发生变化。 现在作为城市市长的Rashof必须明智地选择,以便最小化所有交叉路口之间的路径长度。 帮助Rashof!

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

  1. 计算(C)长度将减少的edges(E')的数量,即L'<大号
  2. 如果C小于或等于K,则为 考虑所有边缘(E'),即更新E
  3. 中所有这些边缘的长度
  4. 其他
    1。基于(L'L)按升序对所有边(E')进行排序 2。按照L'的降序顺序对那些(L'-L)相同的边(E''E')进行排序 3.选择第一个K边(E''E')并更新E中所有这些边的长度

  5. 使用边E和长度L构建图G

  6. 应用任何最短距离算法或DFS来找到每对节点的距离b / w。

  7. 使用优先级队列和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 .为什么这个算法不起作用? 或者在这个算法中应该做什么修改才能被接受? 的参考:
    Rashof, Mayor of EMLand

2 个答案:

答案 0 :(得分:2)

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

答案 1 :(得分:1)

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

假设我们在两个连接的组件A和B之间有边连接,它包含n和m个交叉点,因此,通过将边缘减少x个单位,我们将总距离减少n*m*x。 / p>

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为正)。