POJ 3259 判断负圈

来源:互联网 发布:仙剑奇侠传6激活码淘宝 编辑:程序博客网 时间:2024/04/29 09:23

题意

  • 图中两种边,一种正权值双向边,一种负权值单向边
  • 问是否存在负圈

思路

  • 简单模板题,SPFA如果有节点入队超过节点数次,则存在负圈

实现

#include <iostream>#include <cstring>#include <cstdio>#include <vector>#include <queue>#include <algorithm>using namespace std;const int maxn = 505;vector<pair<int,int> > g[maxn];queue<int> q;int dist[maxn];int inQ[maxn], nums[maxn];int n,m;bool SPFA(int s){    memset(inQ,0,sizeof(inQ));    memset(nums,0,sizeof(nums));    memset(dist,0x3f,sizeof(dist));    while (q.size())        q.pop();    dist[s] = 0;    inQ[s] = 1;    nums[s] = 1;    q.push(s);    while (q.size()){        int u = q.front();        inQ[u] = 0;        q.pop();        for (int e = 0; e< g[u].size();e++){            int v = g[u][e].first;            int w = g[u][e].second;            if (dist[v] > dist[u] + w){                dist[v] = dist[u] + w;                if (inQ[v] == 0){                    q.push(v);                    inQ[v] = 1;                    nums[v]++;                    if (nums[v] > n){                        return false;                    }                }            }        }    }    return true;}int main(){    int w;    int T;    cin>>T;    while (T--){        scanf("%d%d%d",&n,&m,&w);        for (int i=0;i<n;i++){            g[i].clear();        }        for (int i=0;i<m;i++){            int u,v,a;            scanf("%d%d%d",&u,&v,&a);            g[u-1].push_back({v-1,a});            g[v-1].push_back({u-1,a});        }        for (int i=0;i<w;i++){            int u,v,a;            scanf("%d%d%d",&u,&v,&a);            g[u-1].push_back({v-1,-a});        }        if (SPFA(0)){            puts("NO");        }else{            puts("YES");        }    }    return 0;}
0 0