UVALive 6800 The Mountain of Gold (bellman_ford判负环)

题意:给出一个有向图,问从0出发后能不能重新回到0并且总边权和为负。

思路:以0为起点,用bellman_ford找负环,如果有负环,则说明0能走到负环,然后能再找一条从负环到0的路,则实现要求,因为在负权里可以多走几圈保证总边权为负。如何找有没有从负环到0的路:如果有负环,再跑一遍询问,如果进行松弛,则说明边的起点在负环内或负环能到达的点,把这些点标记,然后再扫一遍原来的边,如果边的起点和终点没标记,则反向建边,求出0能不能到达被标记的点,如果能,则负环能到达0,。反之不能。

#include<cstdio>
#include<string>
#include<cstring>
#include<vector>
#include<sstream>
#include<iostream>
#include<cctype>
#include <cmath>
#include <algorithm>
using namespace std;
const int INF = 0x3f3f3f3f;
struct Edge
{
    int from, to, cost;
};
vector<Edge> edge;
vector<Edge> newedge;
int dist[1010];
bool vis[1010];
bool Bellman_ford(int n)
{
    for(int i=0; i<n; i++) dist[i] = INF;
    dist[0] = 0;
    for(int i=0; i<n; i++)
    {
        bool flag = false;
        for(unsigned int j=0; j<edge.size(); j++)
        {
            Edge e = edge[j];
            if(dist[e.from] != INF && dist[e.to] > dist[e.from] + e.cost)
            {
                dist[e.to] = dist[e.from] + e.cost;
                flag = true;
            }
        }
        if(i == n-1)
        {
            if(flag)
                continue;
            else
                return false;
        }
    }
    if(dist[0] < 0)
        return true;
    memset(vis, 0, sizeof(vis));
    {
    for(unsigned int j=0; j<edge.size(); j++)
    {
        Edge e = edge[j];
        if(dist[e.to] > dist[e.from] + e.cost)
        {
            dist[e.to] = dist[e.from] + e.cost;
            vis[e.from] = true;
        }
    }
    }
    for(unsigned int i=0; i<edge.size(); i++)
    {
        Edge e = edge[i];
        if(!vis[e.from] || !vis[e.to])
        {
            newedge.push_back((Edge){e.to, e.from, e.cost});
        }
    }
    for(int i=0; i<n; i++) dist[i] = INF;
    dist[0] = 0;
    for(int i=0; i<n; i++)
    {
        for(unsigned int j=0; j<newedge.size(); j++)
        {
            Edge e = newedge[j];
            if(dist[e.from] != INF && dist[e.to] > dist[e.from] + e.cost)
            {
                dist[e.to] = dist[e.from] + e.cost;
            }
        }
    }
    for(int i=0; i<n; i++)
    {
        if(dist[i] < INF && vis[i])
        {
            return true;
        }
    }
    return false;
}
int main()
{
    int t;
    scanf("%d", &t);
    int ca = 1;
    while(t--)
    {
        int n, m;
        scanf("%d%d", &n, &m);
        edge.clear();
        newedge.clear();
        for(int i=0; i<m; i++)
        {
            int a, b, c;
            scanf("%d%d%d", &a, &b, &c);
            edge.push_back((Edge){a, b, c});
        }
        printf("Case #%d: ", ca++);
        if(Bellman_ford(n))
            printf("possible\n");
        else
            printf("not possible\n");
    }
    return 0;
}
    原文作者:Bellman - ford算法
    原文地址: https://blog.csdn.net/Fungyow/article/details/47146005
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞