POJ 3259 Wormholes (BellmanFord判斷圖是否存在負環)

題目鏈接

POJ3259

題目大意

輸入一個圖,有N(1 N 500)個結點,M(1 M 2500)條正權無向邊,W(1 W 200)條負權單向邊,判斷這個圖中是否存在負權迴路。

分析

判斷圖是否存在負環的模板題。
用Bellman-Ford算法,對所有邊進行N-1輪鬆弛,如果之後還能繼續進行鬆弛,則存在負權迴路。時間複雜度O(N*(M+W))

代碼

#include <iostream>
#include <cstdio>
using namespace std;
const int INF=99999999;
const int MAXM=5500;
const int MAXN=510;
struct Edge
{
    int u,v,w;
}edge[MAXM];//邊集數組
int dis[MAXN],n,m,t,edgenum;
void Add_Edge(int u,int v,int w)//構造邊集數組
{
    edgenum++;
    edge[edgenum].u=u;
    edge[edgenum].v=v;
    edge[edgenum].w=w;
}
bool Bellmen_Ford()
{
    for (int i=1;i<=n;i++)
        dis[i]=INF;
    dis[1]=0;
    for (int k=1;k<=n-1;k++)//對所有邊進行N-1輪鬆弛
    {
        bool flag=false;
        for (int i=1;i<=edgenum;i++)
        {
            int u=edge[i].u;
            int v=edge[i].v;
            if (dis[v]>dis[u]+edge[i].w)
            {
                dis[v]=dis[u]+edge[i].w;
                flag=true;
            }
        }
        if (!flag) break;//如果鬆弛操作已經沒有更新效果了,可提前退出循環
    }
    for (int i=1;i<=edgenum;i++)//如果N-1輪鬆弛後還能繼續鬆弛,則存在負環
        if (dis[edge[i].v]>dis[edge[i].u]+edge[i].w)
            return true;
    return false;
}

int main()
{
    int F,i,u,v,w;
    scanf("%d",&F);
    while (F--)
    {
        scanf("%d%d%d",&n,&m,&t);
        edgenum=0;
        for (i=1;i<=m;i++)
        {
            scanf("%d%d%d",&u,&v,&w);
            Add_Edge(u,v,w);
            Add_Edge(v,u,w);
        }
        for (i=1;i<=t;i++)
        {
            scanf("%d%d%d",&u,&v,&w);
            Add_Edge(u,v,-w);
        }
        bool ans=Bellmen_Ford();
        if (ans) printf("YES\n");
        else printf("NO\n");
    }
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章