poj 3259 Wormholes题解

题目链接:http://poj.org/problem?id=3259

题意:给一个有n个点的图,这些点之间有m条双向的正权值边(两点之间最多一条),还有w条单向的负权值边(权值以正数给出)。判断是否存在负权值回路。

思路:SPFA,判断是否有点出现了超过n次。

注意图是连通的,不用对每一个点都来一次SPFA(这样可能超时)。没有太多坑点,,然而我做的时候死的很惨。。。。

代码

#include
#include
#include
#include
using namespace std;

#define M 6000
#define N 6005
#define INF 1000000000

struct node
{
    int to, val;
    node * next;
};

node * eg[M];
int n, m, w, flog;
int vis[N], cnt[N], dist[N];

void SPFA(int v)
{
    queue q;
    node * p;
    memset(vis, 0, sizeof(vis));
    memset(cnt, 0, sizeof(cnt));
    for (int i = 1; i <= m + w; i++)
    {
        if (i == v)
            dist[i] = 0;
        else
            dist[i] = INF;
    }
    q.push(v);
    vis[v] = 1;
    while (!q.empty())
    {
        int a = q.front();
        q.pop();
        vis[a] = 0;
        cnt[a]++;
        if (cnt[a] > n)
        {
            flog = 1;
            return;
        }
        p = eg[a];
        while (p)
        {
            if (dist[a] < INF && dist[a] + p->val < dist[p->to])
            {

                dist[p->to] = dist[a] + p->val;
                if (!vis[p->to])
                {
                    q.push(p->to);
                    vis[p->to] = 1;
                }
            }
            p = p->next;
        }
    }
}

int main()
{
    int f;
    cin >> f;
    while (f--)
    {
        node * p; flog = 0;
        scanf("%d %d %d", &n, &m, &w);
        for (int i = 0; i <= n; i++)
        {
            eg[i] = NULL;
        }
        for (int i = 1; i <= m + w; i++)
        {
            int s, e, t;
            scanf("%d %d %d", &s, &e, &t);
            p = new node;
            if (i > m)
                t = -t;
            p->to = e; p->val = t;
            p->next = NULL;
            if (eg[s] == NULL)
                eg[s] = p;
            else
            {
                p->next = eg[s];
                eg[s] = p;
            }
            if (i > m)      //前m条路是双向
                continue;
            p = new node;
            p->to = s; p->val = t;
            p->next = NULL;
            if (eg[e] == NULL)
                eg[e] = p;
            else
            {
                p->next = eg[e];
                eg[e] = p;
            }
        }

        SPFA(1);

        if (flog)
            cout << "YES" << endl;
        else
            cout << "NO" << endl;
        for (int i = 0; i <= n; i++)
        {
            while (eg[i])
            {
                p = eg[i]; eg[i] = p->next;
                delete p;
            }
        }
    }
    return 0;
}


你可能感兴趣的:(2016年7月)