poj2449_k short circuit

WC冬眠完了, 寒假过完了(纳尼?居然过完了?!), 又回来继续学hun习dian;
k短路裸题嘛, 具体就是用一个优先队列来不停的更新到每个点的距离, 这样第k次出堆时得到的解就是到该点的k短路。
实际上我们用到中间变量来更新答案。 首先求出所有点到终点t的距离, 可以通过建立反边后跑最短路来求。 然后对于每个点x, 有一个变量w代表从s到x点的当前距离, 也就是说x每次出堆后再进来时w值都会最小程度地变大, 这样就达到了更新答案的目的。 更新的方程可表示为{x, w[x]} => {k, w[x] + d[x][k]}。 需要注意的是, 若一个点已经出过k次堆, 那么它对于解的后续贡献是没有了的, 这是应该果断舍弃。
**CAUTION**: 若s和t一样, 需将k的值加1。 我就在这里跪了一次...
#include <cstdio>
#include <algorithm>
#include <queue>
#define N 1000 + 10
#define M 200000 + 10
#define INF 1000000000

using namespace std;

struct edge
{
    int to, w, next;
}e[M];
int n, m, num, s, t, kth, p[N], flag[N], d[N], cont[N];
struct node
{
    int o, w;
    node() { }
    node(int x, int y)
    { o = x, w = y; }
    bool operator < (const node &a) const
    { return w + d[o] > a.w + d[a.o]; }
};
void read(int &x)
{
    x = 0;
    char c = getchar();
    while(c < '0' || c > '9') c = getchar();
    while(c >= '0' && c <= '9')
    {
        x = 10*x + c - '0';
        c = getchar();
    }
}
void add(int x, int y, int z)
{
    e[++num].to = y;
    e[num].w = z;
    e[num].next = p[x];
    p[x]= num;
}
void init()
{
    int x, y, z;
    read(n), read(m);
    for (int i = 1; i <= m; ++i)
    {
        read(x), read(y), read(z);
        add(x, y, z);
        add(y, x, z);
    }
    read(s), read(t), read(kth);
    if (s == t) ++kth;
}
void spfa()
{
    queue<int>q;
    q.push(t);
    for (int i = 1; i <= n; ++i)
    d[i] = INF;
    d[t] = 0;
    flag[t] = 1;
    while(!q.empty())
    {
        int x = q.front();
        q.pop();
        flag[x] = 0;
        for (int i = p[x]; i; i = e[i].next)
        {
            if (i & 1) continue;
            int k = e[i].to;
            if (d[k] > d[x] + e[i].w)
            {
                d[k] = d[x] + e[i].w;
                if (!flag[k])
                {
                    flag[k] = 1;
                    q.push(k);
                }
            }
        }
    }
}
int Astar()
{
    priority_queue<node>q;
    q.push(node(s, 0));
    node cur;
    while(!q.empty())
    {
        cur = q.top();
        q.pop();
        int x = cur.o, w = cur.w;
        ++cont[x];
        if (x == t && cont[x] == kth) return w;
        if (cont[x] > kth) continue;
        for (int i = p[x]; i; i = e[i].next)
        if (i & 1)
        {
            int k = e[i].to;
            q.push(node(k, w + e[i].w));
        }
    }
    return -1;
}
void deal()
{
    spfa();
    printf("%d\n", Astar());
}
int main()
{
    init();
    deal();
    return 0;
}

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=326385364&siteId=291194637