POJ_3259_spfa

6

POJ 3259

  • 题意:能否通过负边回到过去,意思是求是否存在负权环.

  • 开一个cnt[]记录每一个点访问的次数,如果存在负权环那么一定能一直松弛

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
     #include <iostream>
    #include <queue>
    #include <vector>
    #include <string.h>

    using namespace std;
    const int maxn = 505;

    vector<pair<int,int> > e[maxn];
    bool vis[maxn];
    int dist[maxn];
    int n,m,negative;
    int cnt[maxn];

    bool bellmanford() {
    queue<int> que;
    memset(dist,0x3f,sizeof dist);
    memset(cnt,0,sizeof cnt);
    memset(vis,0,sizeof vis);
    vis[1] = 1; dist[1] = 0;

    que.push(1);

    while (!que.empty()) {
    int cur = que.front(); que.pop();
    vis[cur] = 0;
    for (int i=0; i<e[cur].size(); i++) {
    int to = e[cur][i].first;
    int div = e[cur][i].second;
    if (dist[to] > dist[cur] + div) {
    dist[to] = dist[cur] + div;
    if (!vis[to]) {
    vis[to] = 1;
    que.push(to);
    }
    if (++cnt[to] > n) return 1;
    }
    }
    }
    return false;
    }
    int main() {
    // freopen("a.txt","r",stdin);
    int times;
    cin >> times;
    while (times--) {
    for (int i=1; i<=n; i++) e[i].clear();
    scanf("%d%d%d",&n,&m,&negative);
    int u,v,w;
    for (int i=1; i<=m; i++) {
    scanf("%d%d%d",&u,&v,&w);
    e[u].push_back( make_pair(v,w) );
    e[v].push_back( make_pair(u,w) );
    }
    for (int i=1; i<=negative; i++) {
    scanf("%d%d%d",&u,&v,&w);
    e[u].push_back( make_pair(v,-w) );
    }

    if (bellmanford()) cout << "YES\n";
    else cout << "NO\n";
    for (int i=1; i<=n; i++) e[i].clear();
    }
    return 0;
    }

本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!