[luogu] P3385 【模板】负环

题目描述

暴力枚举/SPFA/Bellman-ford/奇怪的贪心/超神搜索

输入输出格式

输入格式:

 

第一行一个正整数T表示数据组数,对于每组数据:

第一行两个正整数N M,表示图有N个顶点,M条边

接下来M行,每行三个整数a b w,表示a->b有一条权值为w的边(若w<0则为单向,否则双向)

 

输出格式:

 

共T行。对于每组数据,存在负环则输出一行"YE5"(不含引号),否则输出一行"N0"(不含引号)。

 

输入输出样例

输入样例#1: 
2
3 4
1 2 2
1 3 4
2 3 1
3 1 -3
3 3
1 2 3
2 3 4
3 1 -8
输出样例#1:
N0
YE5

说明

n\leq 2000n2000m\leq 3000m3000-10000\leq w\leq 1000010000w10000T\leq 10T10

建议复制输出格式中的字符串。

code

//T到MMP...实测INF不设成10000绝对T
//深吸一口氧
#include<queue>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>

using namespace std;

const int INF = 10000;
const int MAXN = 30000;
int T, n, m;
int head[MAXN * 2], tot = 0;
int dis[MAXN], cnt[MAXN];
bool vis[MAXN];

struct Edge {
    int node, next, value;
}e[MAXN];

inline int read() {
    int num = 0, f = 1; char ch = getchar();
    while (!isdigit(ch)) { if (ch == '-') f = -1; ch = getchar(); }
    while (isdigit(ch)) { num = num * 10 + ch - '0'; ch = getchar(); }
    return num * f;
}

void Add_Edge(int x, int y, int w) {
    e[++tot].node = y; e[tot].value = w; e[tot].next = head[x]; head[x] = tot;
} 

bool SPFA(int s) {
    queue<int> q;
    memset(dis, INF, sizeof(dis));
    memset(vis, false, sizeof(vis));
    memset(cnt, 0, sizeof(cnt));
    dis[s] = 0;
    vis[s] = true;
    cnt[s] = 1;
    q.push(s);
    while (!q.empty()) {
        int h = q.front();
        q.pop();
        vis[h] = false;
        for (int i = head[h], v; ~i, v = e[i].node; i = e[i].next) {
            if (dis[h] + e[i].value < dis[v]) {
                if (++ cnt[v] >= n) return true;
                dis[v] = dis[h] + e[i].value;
                if (!vis[v]) {
                    q.push(v);
                    vis[v] = true;
                }
            }
        } 
    }
    return false;
}

int main() { 
    T = read();
    while (T --) {
        tot = 0;
        memset(head, -1, sizeof(head));
        n = read(); m = read();
        for (int i = 1; i <= m; ++ i) {
            int x = read(), y = read(), w = read();
            Add_Edge(x, y, w);
            if (w >= 0) Add_Edge(y, x, w);
        }
        if(SPFA(1)) printf("YE5\n");
        else printf("N0\n");
    }
    return 0;
} 

 

posted @ 2018-05-23 17:39  wakelin  阅读(134)  评论(0编辑  收藏  举报