pku 3259 Wormholes (Bellman ford判断负权边)

题目链接:  pku3259 Wormholes

 

 之前在数据结构书上看了dijkstra 和floyed(从来没有自己写过)

 

但是有负权边的一直不会

 

所以专门找了题目看看怎么写

 

感觉上bellmanford 跟 dijkstra 处理问题的关键步骤差不多

都是不断的松弛

 

但是bellmanford顺序不同

dijkstra是对每个点进行松弛

 

bellmanford则是对每一条边进行松弛(实际上也是点,松弛有向线段的一个顶点)

 

//pku 3259 Wormholes
//http://poj.org/problem?id=3259

//点数 N ∈ [1,500] ,边数 W ∈ [1,2500] ,虫洞数 W ∈ [1,200]
//每条边取值范围 ∈ [-10000,10000]

#include <stdio.h>
#define INF 10001
#define M 3000

struct
{
	int front,end,num;
}edge[M*2+10];                                                       //双向图 
int dist[M] = {0},pre[M],i,j;
bool bellman_ford(int n,int s,int e)                        //点数n  起点s 边数
{//调用bellman_ford(  n,    1,    e) 
	
	for(i = 1;i <= n;i++)                                             //初始化
	{
		dist[i] = INF;
		
	//	pre[i] = -1;
	}
	
	dist[s] = 0;                                                        //原点的最短距离初始化为0
	
	for(i = 1;i <= n - 1;i++)                                 //循环除起点s外的其他n-1个点
	    
		for(j = 1;j <= e;j++)                                        //对每条边进行松弛操作
	    {
			if(dist[ edge[j].end ] > dist[ edge[j].front ] + edge[j].num)
			{
				dist [edge[j].end ] = dist[ edge[j].front ] + edge[j].num;
			
			//	pre[ edge[j].end ] = edge[j].front;                      //pre记录每个结点的前导
			}
	    }
	
	for(i = 1;i <= e;i++)
	{
	    if(dist[ edge[i].end ] > dist[ edge[i].front ] + edge[i].num)    //成立则存在负环
			return false;
	}
	return true;
}

int main()
{
	int F,n,m,w,i,e,x,y,z;
	
	scanf("%d",&F);

	while(F--)
	{
		e = 1;                                         
        scanf("%d%d%d",&n,&m,&w);                      //点数n 边数m 虫洞数w 

        for(i = 1;i <= m;i++)
        {
			scanf("%d%d%d",&x,&y,&z);
			
			edge[e].front = x;                         //因为都是单向边 
			edge[e].end = y;
			edge[e++].num = z;
			
			edge[e].front = y;                         //所以要反着在来一次
			edge[e].end = x;
			edge[e++].num = z;
        }

        for(i = 1;i <= w;i++)
        {
			scanf("%d%d%d",&x,&y,&z);
			
			edge[e].front = x;                          //接着之前的e给edge赋值 
			edge[e].end = y;
			edge[e++].num = z*-1;                       //负边
		}
        if(! bellman_ford(n,1,e))                       //若false 
			printf("YES\n");                            //存在负环 
        else
			printf("NO\n");
	
//	for(i=1;i<=n;i++)
//		printf("dist[%d]=%d ",i,dist[i]);
//	printf("\n");
//	for(i = 1;i <= e-1;i++)
//	    printf("%d: dist[%d]=%d>dist[%d]=%d+cost=%d?\n",i,edge[i].end,dist[edge[i].end],edge[i].front,dist[edge[i].front],edge[i].num);
//	printf("\n");
	
	}
	return 0;
}

 

    原文作者:Bellman - ford算法
    原文地址: https://blog.csdn.net/dellaserss/article/details/7728413
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞