当最短路变成二维 -_-!

 当最短路变成二维,就会发生非常有意思的事情。。。

问题:给出u v w,表示从u -> v(双向边)所耗的时间为w,又知道没经过一条边,获利为1(对于一天边可以来回走)。求从start到end点,获利至少为k时用的最小时间。。。

如果没有那个k,这个问题直接就是st -> ed的最短路。spfa,dijkstra。。。等等

现在可以设 dis[i][j]表示到从st到 i点经过边数为j 时的最短路。

然后直接spfa,队列中的每个点保留两个值,节点号,和到这个节点的边数。

const int N = 100010;
const int M = 5024;

struct node {
    int to;
    int val;
    int next;
} g[N<<1];

class Graph {
public:
    int head[M], t;

    void init() {
        CL(head, 0XFF); t = 0;
    }

    void add(int u, int v, int w) {
        g[t].to = v; g[t].val = w; g[t].next = head[u];
        head[u] = t++;
    }
} G;

int dis[M][M/10];
bool vis[M][M/10];
int n, k;

struct pnode {
    int v;
    int c;
    pnode() {}
    pnode(int a, int b) : v(a), c(b) {}
};

int solve(int st, int ed) {
    queue q;
    pnode u;
    int v, i, j, sum;

    for(i = 0; i <= n; ++i) {
        for(j = 0; j <= k; ++j) {
            dis[i][j] = inf;
            vis[i][j] = false;
        }
    }
    vis[st][0] = true;
    dis[st][0] = 0;
    q.push(pnode(st, 0));


    while(!q.empty()) {
       u = q.front(); q.pop();
       vis[u.v][u.c] = false;

       for(i = G.head[u.v]; i != -1; i = g[i].next) {
            sum = u.c + 10;
            if(sum > k) sum = k;    // 边数 > k时可以直接压缩到k。
            v = g[i].to;
            if(dis[v][sum] > dis[u.v][u.c] + g[i].val) {
                dis[v][sum] = dis[u.v][u.c] + g[i].val;
                if(!vis[v][sum]) {
                    vis[v][sum] = true;
                    q.push(pnode(v, sum));
                }
            }
       }
    }
    return dis[ed][k];
}

你可能感兴趣的:(当最短路变成二维 -_-!)