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

来源:互联网 发布:12寸windows平板 编辑:程序博客网 时间:2024/06/05 10:38

题意:给出一个有向图,问从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;}


0 0