POJ 3259 Wormholes(判断负环&(Bellman-Ford|SPFA))

来源:互联网 发布:在农村淘宝开店 编辑:程序博客网 时间:2024/06/06 12:20

题目链接:kuangbin带你飞 专题四 最短路练习 F - Wormholes

题意

农场主拥有很多农场,在这些农场之间有很多条路,以及单向的虫洞,每条路走完会花费一定的时间,而冲动可以回到之前的时间,问农场主是否可以通过特定的路径看到出发前的自己?(也就是回到自己出发时间前的出发点)

思路

将农场看做点,路和虫洞看做边,那么显然虫洞是负权边,这样题目就转化为求给定图中是否有负环的问题了。
Bellman-Ford和SPFA都可以进行负环的判断,因为这两个算法以前都没用过,索性就都写了一下,慢慢熟练。
SPFA是对Bellman-Ford进行队列优化的改进版,但提交后反而比Bellman-Ford慢,这点挺奇怪的。
不知道是数据的原因,还是什么?

代码

Bellman-Ford

#include<iostream>#include<cstring>#include<cmath>#include<cstdio>#include<algorithm>using namespace std;const int N = 509;const int MAX = 0x3f3f3f3f;struct Edge{    int u, v, r;}edge[N*N+200];int d[N];bool Bellman_Ford(int n, int e, int src){    for(int i=1; i<=n; i++)        d[i] = MAX;    d[src] = 0;    while(d[src] >= 0)    {        bool flag = true;        for(int i=0; i<e; i++)        {            int u = edge[i].u;            int v = edge[i].v;            int to = d[u] + edge[i].r;            if(d[v] > to)            {                d[v] = to;                flag = false;            }        }        if(flag)            return d[src] < 0;    }    return 1;}int main(){    int T;    scanf("%d", &T);    while(T--)    {        int n, m, w;        scanf("%d%d%d", &n, &m, &w);        for(int i=0; i<m; i++)        {            int a, b, c;            scanf("%d%d%d", &a, &b, &c);            edge[i].u = a;            edge[i].v = b;            edge[i].r = c;            edge[i+m].u = b;            edge[i+m].v = a;            edge[i+m].r = c;        }        for(int i=0; i<w; i++)        {            int a, b, c;            scanf("%d%d%d", &a, &b, &c);            edge[2*m+i].u = a;            edge[2*m+i].v = b;            edge[2*m+i].r = -c;        }        if(Bellman_Ford(n, m*2+w, 1))            printf("YES\n");        else            printf("NO\n");    }    return 0;}

SPFA

#include<iostream>#include<cstring>#include<cmath>#include<cstdio>#include<algorithm>#include<queue>using namespace std;const int N = 509;const int MAX = 0x3f3f3f3f;struct Edge{    int u, v, r, next;}edge[N*N+200];int d[N];int h[N];bool vis[N];int cnt[N];bool spfa(int n){    memset(vis, 0, sizeof(vis));    memset(cnt, 0, sizeof(cnt));    for(int i=1; i<=n; i++)        d[i] = MAX;    d[1] = 0;    vis[1] = 1;    cnt[1]++;    queue<int> q;    q.push(1);    while(!q.empty())    {        int x = q.front();        vis[x] = 0;        q.pop();        for(int i = h[x]; i!=-1; i = edge[i].next)        {            int v = edge[i].v;            int to = edge[i].r + d[edge[i].u];            if(d[v] > to)            {                d[v] = to;                if(!vis[v])                {                    vis[v] = 1;                    q.push(v);                    if(++cnt[v] > n)                        return 1;                }            }        }    }    return 0;}int main(){    int T;    scanf("%d", &T);    while(T--)    {        int n, m, w;        memset(h, -1, sizeof(h));        scanf("%d%d%d", &n, &m, &w);        for(int i=0; i<m; i++)        {            int a, b, c;            scanf("%d%d%d", &a, &b, &c);            edge[i].next = h[a];            edge[i].u = a;            edge[i].v = b;            edge[i].r = c;            h[a] = i;            edge[i+m].next = h[b];            edge[i+m].u = b;            edge[i+m].v = a;            edge[i+m].r = c;            h[b] = i+m;        }        for(int i=0; i<w; i++)        {            int a, b, c;            scanf("%d%d%d", &a, &b, &c);            edge[2*m+i].next = h[a];            edge[2*m+i].u = a;            edge[2*m+i].v = b;            edge[2*m+i].r = -c;            h[a] = 2*m+i;        }        if(spfa(n))            printf("YES\n");        else            printf("NO\n");    }    return 0;}
0 0
原创粉丝点击