Finally, I began to take graph theory seriously.
I have heard that I have been raising the group, and I have been moving very little. I have been learning some things since I started to improve my computer room.
Template question link
This is a question for finding negative loops. In theory, we all use spfa to judge negative loops.
But I think Bellman-Ford is better.
In addition, in this template question, the spfa has opened O2, and the bellman does not enable O2, which is faster than the spfa?
Why?
Because
About spfa
-- He is dead.
(The basic owner of the IDC is dijistra)
However, dijistra cannot solve the negative ring problem.
Therefore, select bellman and spfa (queue-optimized bellman)
You can also use other methods, such
Spfa dead algorithm ideas
Because when a negative ring occurs, it will keep repeating ......
Then TLE
Therefore, add a CNT array to the original spfa to record the number of times a team exists.
If the number of teams is greater than the number of points, it indicates that a negative ring must appear.
Therefore, you can add it to the judgment.
Digress
Previously, xzjds told me about the storage of the adjacent table, but later I found that it is generally called the chain forward star instead of the adjacent table ......
If not, Baidu
To store edges, you can also use vector containers and Xuanxue struct (which will be used in bellman)
Code
// luogu-judger-enable-o2#include<bits/stdc++.h>#define memset0(a) memset(a,0,sizeof a)#define memset1(a) memset(a,127,sizeof a)#define N 500005using namespace std;int tot,m,n,s;int ne[N], la[N], link[N], co[N], dis[N];int cnt[N];//importantbool vis[N];inline int read() { int f = 1, x = 0; char ch; do { ch = getchar(); if (ch == ‘-‘)f = -1; } while (ch<‘0‘ || ch>‘9‘); do { x = x * 10 + ch - ‘0‘; ch = getchar(); } while (ch >= ‘0‘&&ch <= ‘9‘); return f * x;}void add(int x, int y, int z){ tot++; ne[tot] = y; co[tot] = z; la[tot] = link[x]; link[x] = tot;}bool spfa(int s){ memset1(dis); memset0(vis); memset0(cnt); queue<int>q; q.push(s); vis[s] = true; dis[s] = 0; while (!q.empty()) { int now = q.front(); q.pop(); vis[now] = false;//? if (cnt[now] >= n) return true; for (int k = link[now]; k; k = la[k]) { if (dis[ne[k]] > dis[now] + co[k]) { dis[ne[k]] = dis[now] + co[k]; if (vis[ne[k]] == false) { q.push(ne[k]); vis[ne[k]] = true; cnt[ne[k]]++; if (cnt[ne[k]] >= n) return true; } } } } return false;}int main(){ int T=read(); while (T--) { memset0(link); n = read(), m = read(); s = 1; tot = 0;; for (int i = 1; i <= m; i++) { int x=read(), y=read(), z=read(); add(x, y, z); if (z >= 0) add(y, x, z); } if(spfa(s))puts("YE5"); else puts("N0"); } return 0;}
Spfa
Yes, it will be TLE without O2. Only 90 points.
Because this algorithm won't be optimized, we learned a better way to judge the negative ring of Bellman.
Bellman-Ford algorithm ideas
We can set the DIS array to 0 at the beginning.
First, perform all the relaxation operations (relaxing once)
Then relax again. If it can relax, there is a negative ring.
Compared with spfa, when the number of data points is small, the time is faster than spfa.
Of course, if the RP is not good, the spfa speed will be faster.
Why is there a problem every time?
The edge storage method is shown in daxie @ planet6174.
It is very mysterious but easy to use.
Code
#include<bits/stdc++.h>#define N 500005using namespace std;int tot,m,n,s;int dis[N];inline int read() { int f = 1, x = 0; char ch; do { ch = getchar(); if (ch == ‘-‘)f = -1; } while (ch<‘0‘ || ch>‘9‘); do { x = x * 10 + ch - ‘0‘; ch = getchar(); } while (ch >= ‘0‘&&ch <= ‘9‘); return f * x;}struct eg{ int u,v,w; eg(int u = 0, int v = 0, int w = 0) : u(u), v(v), w(w) {}} edge[N];bool bellman_ford(){ memset(dis,0,sizeof(dis)); for(int i=1;i<=n-1;i++) for(int j=1;j<=m;j++) if (dis[edge[j].u] + edge[j].w < dis[edge[j].v]) dis[edge[j].v] = dis[edge[j].u] + edge[j].w; for (int j = 1; j <= m; j++) if (dis[edge[j].u] + edge[j].w < dis[edge[j].v]) return true; return false;}int main(){ int T=read(); while (T--) { n = read(), m = read();; for (int i = 1; i <= m; i++) { edge[i].u=read(), edge[i].v=read(), edge[i].w=read(); edge[i].u--; edge[i].v--; if (edge[i].w >= 0) { ++i; ++m; edge[i] = eg(edge[i - 1].v, edge[i - 1].u, edge[i - 1].w); } } if(bellman_ford()) puts("YE5"); else puts("N0"); } return 0;}
Bellman-Ford
That's it.
[Negative ring problem solution] Use spfa And Bellman-Ford