2013-team5/andrew/13/E

从 Trac 迁移的文章

这是从旧校内 Wiki 迁移的文章,可能存在一些样式问题,您可以向 memset0 反馈。

原文章内容如下:

{{{
#include <vector>
#include <queue>
#include <cstdio>
#include <cassert>
#include <cstring>
#include <cstdlib>
#include <algorithm>

using namespace std;

typedef long long LL;

const int MAXN = 2000 + 10;
const long long inf = 1ll<<62;

LL grid[MAXN][MAXN];
vector<int> G[MAXN];
vector<LL> W[MAXN];
LL dis[MAXN];
bool vis[MAXN], mark[MAXN], path[MAXN];
int pre[MAXN];
int N, M, S;
LL lower;

void dfs(int u) {
    mark[u] = 1;
    for (int i = 0; i < (int)G[u].size(); ++ i) {
        int v = G[u][i];
        if (mark[v]) continue;
        dfs(v);
    }
}

int times[MAXN];

void spfa() {
    queue<int> Q;
    while (!Q.empty()) Q.pop();
    for (int i = 0; i < N; ++ i) {
        dis[i] = inf;
        vis[i] = 0;
        times[i] = 0;
    }
    if (mark[S]) return;
    dis[S] = 0; vis[S] = 1; Q.push(S); times[S] = 1;
    while (!Q.empty()) {
        int u = Q.front(); Q.pop();
        if (times[u] > N || dis[u] < lower) {
            if (!mark[u]) dfs(u);
            continue;
        }
        vis[u] = 0;
        for (int i = 0; i < (int)G[u].size(); ++ i) {
            int v = G[u][i];
            LL w = W[u][i];
            if (mark[v]) continue;
            if (dis[v] > dis[u] + w) {
                dis[v] = dis[u] + w;
                if (!vis[v]) {
                    times[v] ++;
                    //assert(times[v] <= N);
                    Q.push(v);
                    vis[v] = 1;
                }
            }
        }
    }
}

int main() {
    freopen("path.in", "r", stdin);
    freopen("path.out", "w", stdout);
    scanf("%d%d%d", &N, &M, &S); S --;
    for (int i = 0; i < N; ++ i) {
        for (int j = 0; j < N; ++ j)
            grid[i][j] = inf;
    }
    for (int i = 0; i < N; ++ i) {
        G[i].clear();
        W[i].clear();
    }
    for (int i = 0; i < M; ++ i) {
        int x, y;
        LL z;
        scanf("%d%d%I64d", &x, &y, &z);
        x --; y --;
        grid[x][y] = min(grid[x][y], z);
    }
    lower = 0;
    for (int i = 0; i < N; ++ i) {
        for (int j = 0; j < N; ++ j) {
            if (grid[i][j] == inf) continue;
            if (grid[i][j] < 0) lower += grid[i][j];
            G[i].push_back(j);
            W[i].push_back(grid[i][j]);
        }
    }
    memset(vis, 0, sizeof(vis));
    memset(mark, 0, sizeof(mark));
    memset(path, 0, sizeof(path));
    spfa();
    for (int i = 0; i < N; ++ i) {
        if (mark[i]) puts("-");
        else {
            if (dis[i] == inf) puts("*");
            else printf("%I64d\n", dis[i]);
        }
    }
    fclose(stdin); fclose(stdout);
    return 0;
}
}}}
#include <vector>
#include <queue>
#include <cstdio>
#include <cassert>
#include <cstring>
#include <cstdlib>
#include <algorithm>
using namespace std;
typedef long long LL;
const int MAXN = 2000 + 10;
const long long inf = 1ll<<62;
LL grid[MAXN][MAXN];
vector<int> G[MAXN];
vector<LL> W[MAXN];
LL dis[MAXN];
bool vis[MAXN], mark[MAXN], path[MAXN];
int pre[MAXN];
int N, M, S;
LL lower;
void dfs(int u) {
    mark[u] = 1;
    for (int i = 0; i < (int)G[u].size(); ++ i) {
        int v = G[u][i];
        if (mark[v]) continue;
        dfs(v);
    }
}
int times[MAXN];
void spfa() {
    queue<int> Q;
    while (!Q.empty()) Q.pop();
    for (int i = 0; i < N; ++ i) {
        dis[i] = inf;
        vis[i] = 0;
        times[i] = 0;
    }
    if (mark[S]) return;
    dis[S] = 0; vis[S] = 1; Q.push(S); times[S] = 1;
    while (!Q.empty()) {
        int u = Q.front(); Q.pop();
        if (times[u] > N || dis[u] < lower) {
            if (!mark[u]) dfs(u);
            continue;
        }
        vis[u] = 0;
        for (int i = 0; i < (int)G[u].size(); ++ i) {
            int v = G[u][i];
            LL w = W[u][i];
            if (mark[v]) continue;
            if (dis[v] > dis[u] + w) {
                dis[v] = dis[u] + w;
                if (!vis[v]) {
                    times[v] ++;
                    //assert(times[v] <= N);
                    Q.push(v);
                    vis[v] = 1;
                }
            }
        }
    }
}
int main() {
    freopen("path.in", "r", stdin);
    freopen("path.out", "w", stdout);
    scanf("%d%d%d", &N, &M, &S); S --;
    for (int i = 0; i < N; ++ i) {
        for (int j = 0; j < N; ++ j)
            grid[i][j] = inf;
    }
    for (int i = 0; i < N; ++ i) {
        G[i].clear();
        W[i].clear();
    }
    for (int i = 0; i < M; ++ i) {
        int x, y;
        LL z;
        scanf("%d%d%I64d", &x, &y, &z);
        x --; y --;
        grid[x][y] = min(grid[x][y], z);
    }
    lower = 0;
    for (int i = 0; i < N; ++ i) {
        for (int j = 0; j < N; ++ j) {
            if (grid[i][j] == inf) continue;
            if (grid[i][j] < 0) lower += grid[i][j];
            G[i].push_back(j);
            W[i].push_back(grid[i][j]);
        }
    }
    memset(vis, 0, sizeof(vis));
    memset(mark, 0, sizeof(mark));
    memset(path, 0, sizeof(path));
    spfa();
    for (int i = 0; i < N; ++ i) {
        if (mark[i]) puts("-");
        else {
            if (dis[i] == inf) puts("*");
            else printf("%I64d\n", dis[i]);
        }
    }
    fclose(stdin); fclose(stdout);
    return 0;
}