您的位置:首页 > 其它

poj 3259 spfa/bellman判断负圈(虫洞)

2015-07-28 20:38 375 查看
题意:判断有向连通图(图中有重边)中是否存在负权环。给定N个点,M条双向正权边,W条单向负权边。

思路:用bellman或者spfa均可。在bellman算法中的表述为:在求出经过了n-1条边的最短路dist[k]之后,再对每条边<u,k>判断一下:加入这条边是否会使得顶点k的最短路径值再缩短,即判断:dist[u]+w(u,k)<dist[k] 是否成立,如果成立,则说明存在从源点可达的负权值回路。

在spfa中的表述为:若一个点最短路被改进的次数达 到n ,则有负权环。

bellman版本:

#include <stdio.h>
#include <string.h>
#define N 522
int T,n,m,w,edgenum;
struct edge{
int x,y,w;
}e[N*N/2];
int dis
;
int bellman_ford(){
int i,j;
for(i = 0;i<n-1;i++){
for(j = 0;j<edgenum;j++){
if(dis[e[j].x]+e[j].w < dis[e[j].y]){

dis[e[j].y] = dis[e[j].x]+e[j].w;
}
}
}
for(j = 0;j<edgenum;j++){
if(dis[e[j].y] > dis[e[j].x]+e[j].w)
return 1;
}
return 0;
}
int main(){
//freopen("a.txt","r",stdin);
scanf("%d",&T);
while(T--){
int i,x,y,len;
edgenum = 0;
memset(dis,0,sizeof(dis));
scanf("%d %d %d",&n,&m,&w);
for(i = 0;i<m;i++){
scanf("%d %d %d",&x,&y,&len);
e[edgenum].x = x;
e[edgenum].y = y;
e[edgenum++].w = len;
e[edgenum].x = y;
e[edgenum].y = x;
e[edgenum++].w = len;
}
for(i = 0;i<w;i++){
scanf("%d %d %d",&x,&y,&len);
e[edgenum].x = x;
e[edgenum].y = y;
e[edgenum++].w = -len;
}
if(bellman_ford())
printf("YES\n");
else
printf("NO\n");
}
return 0;
}


spfa版本:

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>
#include <cstdlib>
using namespace std;
#define INF 0x3fffffff
#define N 1005
struct edge{
int y,next,w;
}e[5205];
int first
,top,dis
,num
,used
;
int T,n,m,k;
queue<int> q;
void add(int x,int y,int w){
e[top].y = y;
e[top].w = w;
e[top].next = first[x];
first[x] = top++;
}
int relax(int x,int y,int w){
if(dis[y] > dis[x]+w){
dis[y] = dis[x]+w;
return 1;
}
return 0;
}
int spfa(){
int i,now;
q.push(1);
for(i = 2;i<=n;i++)
dis[i] = INF;
dis[1] = 0;
memset(num, 0, sizeof(num));
memset(used, 0, sizeof(used));
used[1] = 1;
while(!q.empty()){
now = q.front();
q.pop();
used[now] = 0;
for(i = first[now];i!=-1;i=e[i].next){
if(relax(now,e[i].y,e[i].w) && !used[e[i].y]){
used[e[i].y] = 1;
q.push(e[i].y);
num[e[i].y]++;
if(num[e[i].y] == n)
return 1;
}
}
}
return 0;
}
int main(){
scanf("%d",&T);
while(T--){
int i,a,b,w;
while(!q.empty())
q.pop();
memset(first, -1, sizeof(first));
top = 0;
scanf("%d %d %d",&n,&m,&k);
for(i = 1;i<=m;i++){
scanf("%d %d %d",&a,&b,&w);
add(a,b,w);
add(b,a,w);
}
for(i = 1;i<=k;i++){
scanf("%d %d %d",&a,&b,&w);
add(a,b,-w);
}
if(spfa())
printf("YES\n");
else
printf("NO\n");
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: