您的位置:首页 > 其它

poj 3259 Wormholes题解

2016-07-07 19:23 483 查看
题目链接:http://poj.org/problem?id=3259

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

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

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

代码

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
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
, cnt
, dist
;

void SPFA(int v)
{
queue<int> 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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息