IT民工
加油!

http://poj.org/problem?id=3259
  题意大致是N个点, M条正常的边(双向)边权为正,W个虫洞,边权为负,想要

我们判断回路中是否存在一个负圈。学习了bellman-ford算法来求负环,松弛结束后判断是否

存在最短路,不存在则有负环。

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

const int maxn = 1 << 9, inf = 0x3f3f3f3f;
int dist[maxn];
int N, M, W, es;

struct Edge
{
    int u, v, w;
}e[maxn * maxn];

void addedge(int u, int v, int w)
{
    e[es].u = u, e[es].v = v, e[es ++].w = w;
}

void readgraph()
{
    int u, v, w;
    es = 0;
    scanf("%d%d%d", &N, &M, &W);
    for(int i = 0; i < M; i ++)
    {
        scanf("%d%d%d", &u, &v, &w);
        addedge(u, v, w);
        addedge(v, u, w);
    }
    for(int i = 0; i < W; i ++)
    {
        scanf("%d%d%d", &u, &v, &w);
        addedge(u, v, -w);
    }
}

void relax(int es)
{
    int u = e[es].u, v = e[es].v, w = e[es].w;
    if(dist[v] > dist[u] + w)
        dist[v] = dist[u] + w;
}

bool bellman(int src)
{
    for(int i = 1; i < N; i ++)
        dist[i] = inf;
    dist[src] = 0;
    for(int i = 0; i < N - 1; i ++)
    {
        for(int j = 0; j < es; j ++)
        {
            relax(j);
        }
    }
    for(int i = 0; i < es; i ++)
    {
        if(dist[e[i].v] > dist[e[i].u] + e[i].w)
            return false;
    }
    return true;
}

int main()
{
    int T;
    scanf("%d", &T);
    while(T --)
    {
        readgraph();
        if(!bellman(0))
            printf("YES\n");
        else
            printf("NO\n");
    }
    return 0;
}

 

 

下面就是这个算法的过程: 

Bellman-Ford(G,w,s) :boolean //图G ,边集 函数 w ,s为源点

 

  1 for each vertex v ∈ V(G) do //初始化 1阶段

 

  2 d[v] ←+∞

 

  3 d[s] ←0; //1阶段结束

 

  4 for i=1 to |v|-1 do //2阶段开始,双重循环。

 

  5 for each edge(u,v) ∈E(G) do //边集数组要用到,穷举每条边。

 

  6 If d[v]> d[u]+ w(u,v) then //松弛判断

 

  7 d[v]=d[u]+w(u,v) //松弛操作 2阶段结束

 

  8 for each edge(u,v) ∈E(G) do

 

  9 If d[v]> d[u]+ w(u,v) then

 

  10 Exit false

 

  11 Exit true

posted on 2012-04-02 10:58  找回失去的  阅读(216)  评论(0编辑  收藏  举报