ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

基于A*算法的KSP问题求解

2021-07-24 10:00:43  阅读:137  来源: 互联网

标签:src vector KSP 求解 int topo 算法 cost cur


#include <bits/stdc++.h>

using namespace std;

constexpr int INF = 1e9;

vector<int> H; // h(x)

void LoadTopo(vector<vector<int>> &topo, int nodeNum)
{
    topo.resize(nodeNum + 1);
    int u, v, w;
    // while (cin >> u >> v >> w) {
    //     topo[u].push_back(v);
    // }
    while (~scanf("%d %d %d", &u, &v, &w)) {
        topo[u].push_back(v);
    }
    return;
}

void ReverseTopo(const vector<vector<int>> &topo, vector<vector<int>> &revTopo)
{
    revTopo.resize(topo.size());
    for (int u = 0; u < topo.size(); ++u) {
        for (int v : topo[u]) {
            revTopo[v].push_back(u);
        }
    }
}

constexpr int TOPO_LINK_DEFAULT_COST  = 1;

void Dijkstra(const vector<vector<int>> &topo, vector<int> &cost, int src)
{
    using P = pair<int, int>;
    priority_queue<P, vector<P>, greater<P>> que;
    cost.resize(topo.size());
    fill(cost.begin(), cost.end(), INF);
    cost[src] = 0;
    que.push((P){cost[src], src});
    while (!que.empty()) {
        P curP = que.top();
        que.pop();
        int u = curP.second;
        if (cost[u] < curP.first) {
            continue;
        }
        for (int v : topo[u]) {
            if (cost[v] > cost[u] + TOPO_LINK_DEFAULT_COST) {
                cost[v] = cost[u] + TOPO_LINK_DEFAULT_COST;
                que.push((P){cost[v], v});
            }
        }
    }
}

void PrintPath(const vector<int> &path)
{
    cout << "path cost : " << path.size() - 1 << endl;
    for (int i = 0; i < path.size(); ++i) {
        cout << path[i];
        if (i != path.size() - 1) {
            cout << "->";
        }
    }
    cout << endl;
}

typedef struct CurTraverStatus {
    int lstId;
    int curId;
    int curNodeId;
    int g; // g(x)

    void pt()
    {
        cout << "curNodeId " << curNodeId << " lstId " << lstId << " curId " << curId << " val: " << g << " " << H[curNodeId] << endl; 
    }

    bool operator < (const CurTraverStatus &other) const {
        return g + H[curNodeId] > other.g + H[other.curNodeId]; 
    }
} CurTraverStatus;

void Recordpath(map<int, CurTraverStatus> &mem, CurTraverStatus curStatus, int src)
{
    vector<int> path;
    CurTraverStatus &cur = curStatus;
    while (true) {
        path.push_back(cur.curNodeId);
        if (cur.curNodeId == src) {
            break;
        }
        cur = mem[cur.lstId];
    }
    reverse(path.begin(), path.end());
    PrintPath(path);
}

void KSPByAStartAlgo(const vector<vector<int>> &topo, int src, int dest, int k)
{
    static int ID = 0;
    map<int, CurTraverStatus> mem;
    priority_queue<CurTraverStatus> que;
    CurTraverStatus first = (CurTraverStatus){ID, ID++, src, 0};
    mem[first.curId] = first;
    que.push(first);
    vector<int> cnt(topo.size(), 0);
    vector<bool> isInQueue(topo.size(), false);
    isInQueue[src] = true;
    while (!que.empty()) {
        CurTraverStatus cur = que.top();
        que.pop();
        // cur.pt();
        cnt[cur.curNodeId]++;
        if (cnt[cur.curNodeId] > k) {
            continue;
        }
        if (cur.curNodeId == dest) {
            // 第 cnt[cur.curNodeId] 小的路径生成成功
            // cout << "\ncurK = " << cnt[cur.curNodeId] << endl;
            // Recordpath(mem, cur, src);
            if (cnt[cur.curNodeId] == k) {
                break;
            }
        }
        for (int v : topo[cur.curNodeId]) {
            // cout << cur.curNodeId << " -> " << v << endl;
            if (isInQueue[v]) {
                // 该判断避免因为想走短的路绕环
                continue;
            }
            CurTraverStatus newStatus = (CurTraverStatus){cur.curId, ID++, v, cur.g + TOPO_LINK_DEFAULT_COST};
            mem[newStatus.curId] = newStatus;
            que.push(newStatus);
        }
    }
}

int main()
{
    freopen("in.txt", "r", stdin);
    // ios::sync_with_stdio(0);
    // cin.tie(0);
    clock_t start;
    clock_t end;

    start = clock();

    int nodeNum, edgeNum, src, dest, k;
    // cin >> nodeNum >> edgeNum >> src >> dest >> k;
    scanf("%d %d %d %d %d", &nodeNum, &edgeNum, &src, &dest, &k);

    vector<vector<int>> topo;
    LoadTopo(topo, nodeNum);

    end = clock();

    cout << "loadTopo " << (double)(end - start) / CLOCKS_PER_SEC << "s" << endl;
    

    start = clock();

    vector<vector<int>> revTopo;
    ReverseTopo(topo, revTopo);

    Dijkstra(revTopo, H, dest);
    if (H[src] == INF) {
        cout << "can't arrival" << endl;
        return 0;
    }

    KSPByAStartAlgo(topo, src, dest, k);

    end = clock();
    cout << "calc " << (double)(end - start) / CLOCKS_PER_SEC << "s" << endl;
    return 0;
}

制造用例python代码

n = 4000
m = n * (n - 1)
s = 1
t = n
k = 1000
print('{0} {1} {2} {3} {4}'.format(n, m, s, t, k))
for i in range(1, n + 1):
    for j in range(i + 1, n + 1):
        print('{0} {1} 1'.format(i, j))
        print('{0} {1} 1'.format(j, i))

性能:
4000个点,4000 * 3999 条边取前1000条最短路的开销
在这里插入图片描述

使用方法:
1.将上面的python代码的输出重定向到in.txt
2.编译运行上面的cpp代码

标签:src,vector,KSP,求解,int,topo,算法,cost,cur
来源: https://blog.csdn.net/qq_37337268/article/details/119053198

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有