[負環問題解法]使用spfa和bellman-ford

來源:互聯網
上載者:User

標籤:get   put   基本   操作   hellip   前向星   else   問題   mem   

終於開始認真對待圖論了

因為聽說一直是提高組的,動得很少,直到現在機房打提高的氛圍下,開始學一些皮毛的東西

模板題目連結

這是一道求負環的題目,照理來說大家都是用spfa來判斷負環的

但是我覺得bellman-ford更優

並且在這個模板題目中,spfa開O2過,bellman不開O2還比spfa快?

為什麼呢?

因為

關於spfa

——他死了

(所以機房基本所有人轉dijistra了)

但是dijistra無法解決負環問題

因此選擇bellman和spfa(隊列最佳化的bellman)

其實還可以用其他方法過掉,比如

 

SPFA他死了演算法思路

因為出現負環的時候會一直迴圈迴圈迴圈……

然後TLE

所以在原版spfa上加一個cnt數組記錄一個點出隊的次數

如果出隊次數大於點數,就說明一定出現負環了

因此加給判斷就可以了

題外話

之前xzjds給我講了鄰接表儲存,但是後來發現其實廣泛叫做鏈式前向星而不是叫做鄰接表……

如果不會的話可以百度

要儲存邊的話還可以用向量容器和玄學結構體(將會在bellman裡使用)

代碼
// 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

是的,不加O2會TLE。只有90分。

由於本蒟蒻不會最佳化,因此學習了更好的bellman判斷負環

Bellman-ford演算法思路

可以把dis數組一開始都設為0

先全部鬆弛操作一遍(relaxing一遍)

然後再去鬆弛,如果能鬆弛,就是有負環

這個相對spfa來說,當資料點數小的時候,時間是比spfa快的

當然如果RP不好spfa速度會更快

為什麼每次都有題外話

用的邊的儲存方式是從大佬@Planet6174 看來的

感覺非常玄學但是很容易使用

代碼
#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

就是這樣了

[負環問題解法]使用spfa和bellman-ford

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.