谁能教我SPFA怎么判负环qwq

灌水区

或者文章也行
by __gcd @ 2020-01-22 10:20:30


入队次数来判
by 十十十十 @ 2020-01-22 10:21:18


如有点入队次数超过n,则有环(最短路负环,反之)。
by A1443356159 @ 2020-01-22 10:22:33


@[十十十十](/user/153802) 然后这玩意只有10分 ```cpp #include<bits/stdc++.h> #define ll long long using namespace std; const int MAX_INT = (1 << 30); const ll MAX_LONG = ((ll)1 << (ll)60); struct In { template <typename T> inline In& operator >> (T &x) { char c = getchar(); int op = 0; x = 0; while(c ^ '-' && !isdigit(c))c = getchar(); if(c == '-')op = 1, c = getchar(); while(isdigit(c))x = (x << 1) + (x << 3) + (c ^ 48), c = getchar(); if(op)x = -x; return *this; } } in; const int N = 10010; const int INF = 2147483647; struct Edge { int to, w; }; int n, m; int dis[N], times[N]; bool vis[N]; vector<Edge> nbr[N]; void init() { memset(times, 0, sizeof(times)); for(int i = 1; i <= n; i++) { nbr[i].clear(); } return ; } bool spfa() { queue<int> q; for(int i = 1; i <= n; i++) { dis[i] = INF; } dis[1] = 0; vis[1] = true; q.push(1); times[1]++; while(q.empty() == false) { int cur = q.front(); q.pop(); vis[cur] = false; for(int i = 0; i < nbr[cur].size(); i++) { int v = nbr[cur][i].to; int w = nbr[cur][i].w; if(dis[cur] + w < dis[v]) { dis[v] = dis[cur] + w; if(vis[v] == false) { q.push(v); vis[v] = true; times[v]++; } if(times[v] > n)return false; } } } return true; } int main() { int t; in >> t; while(t--) { in >> n >> m; init(); for(int i = 1; i <= m; i++) { int u, v, w; in >> u >> v >> w; nbr[u].push_back((Edge){v, w}); } bool ans = spfa(); if(ans == false)cout << "YE5" << endl; else cout << "N0" << endl; } return 0; } ```
by __gcd @ 2020-01-22 10:23:02


把 vis 数组去掉
by Lucky_Xiang @ 2020-01-22 10:31:22


提高的那本书上有的,spfa单点入队次数超过n是一种,有大环会T,一般的处理方法是 ```cpp if((double)clock()/CLOCKS_PER_SEC>0.9) exit(printf("有环")&0); ``` 或者写dfs版的spfa,如果dfs栈内有当前节点且权变小就有负环
by bessie_goes_moo @ 2020-01-22 10:37:17


@[幸运翔](/user/120742) 还是10分
by __gcd @ 2020-01-22 10:41:00


@[bessie_goes_moo](/user/125322) 目前只会bfs
by __gcd @ 2020-01-22 10:41:43


@[一只大头](/user/149192) 在进行 SPFA 时,用一个数组 $cnt_i $来标记每个顶点入队次数。如果一个顶点入队次数 $cnt_i$ 大于顶点总数 $n$,则该图包含负环。
by Stephen_Curry @ 2020-01-22 10:58:52


参考代码: ```cpp const int inf = 0x3f3f3f3f; struct node { int v, w; node() { } node(int vv, int ww) { v = vv; w = ww; } }; vector<node> g[N]; int n, m, s; int d[N], cnt[N]; bool in_queue[N]; queue<int> q; bool spfa(int s) { memset(d, 0x3f, sizeof(d)); d[s] = 0; in_queue[s] = true; q.push(s); cnt[s]++; while (!q.empty()) { int v = q.front(); q.pop(); in_queue[v] = false; for (int i = 0; i < g[v].size(); i++) { int x = g[v][i].v; if (d[x] > d[v] + g[v][i].w) { d[x] = d[v] + g[v][i].w; if (!in_queue[x]) { q.push(x); in_queue[x] = true; cnt[x]++; if (cnt[x] > n) { return true; } } } } } return false; } ```
by Stephen_Curry @ 2020-01-22 11:00:42


| 下一页