POJ3259-Wormholes

全解题报告索引目录 -> 【北大ACM – POJ试题分类

转载请注明出处:http://exp-blog.com

-------------------------------------------------------------------------

 

 

提示:

利用虫洞的时光旅行,很有趣的一道题。涉及到图论的知识,关键是构造图,用Bellman-Ford算法找出负权环

Bellman-Ford算法核心在于松弛,具体可以百度,这里就不重复前人的智慧了O(∩_∩)O哈哈~

需要注意的就是输入说明Input这部分,很多人读不懂这段题意:

正权(双向)边部分:
Line 1 of each farm: Three space-separated integers respectively: N, M, and W


Lines 2~M+1 of each farm: Three space-separated numbers (S, E, T) that describe, respectively: a bidirectional path between S and E that requires T seconds to traverse.

Two fields might be connected by more than one path.

 

负权(单向)边部分:
Lines M+2~M+W+1 of each farm: Three space-separated numbers (S,E, T) that describe, respectively: A one way path from S toE that also moves the traveler back T seconds.

 

 

 

//Memory Time 
//308K   204MS 

#include<iostream>
using namespace std;

int dis[1001];      //源点到各点权值
const int max_w=10001;      //无穷远

class weight
{
public:
    int s;
	int e;
	int t;
}edge[5200];

int N,M,W_h; //N (1≤N≤500)fields 顶点数
             //M (1≤M≤2500)paths 正权双向边
             //W_h (1≤W≤200) wormholes 虫洞(回溯),负权单向边
int all_e;   //边集(边总数)

bool bellman(void)
{
    bool flag;

	/*relax*/

    for(int i=0;i<N-1;i++)
    {
        flag=false;
        for(int j=0;j<all_e;j++)
            if(dis[edge[j].e] > dis[edge[j].s] + edge[j].t)
			{
                dis[edge[j].e] = dis[edge[j].s] + edge[j].t;
                flag=true;         //relax对路径有更新
			}
        if(!flag)   
            break;  //只要某一次relax没有更新,说明最短路径已经查找完毕,或者部分点不可达,可以跳出relax
    }

	/*Search Negative Circle*/

    for(int k=0;k<all_e;k++)
        if( dis[edge[k].e] > dis[edge[k].s] + edge[k].t)
            return true;

    return false;
}
int main(void)
{
    int u,v,w;

	int F;
    cin>>F;
    while(F--)
    {
		memset(dis,max_w,sizeof(dis));    //源点到各点的初始值为无穷,即默认不连通

        cin>>N>>M>>W_h;

        all_e=0;      //初始化指针

		/*read in Positive Paths*/

        for(int i=1;i<=M;i++)
        {
            cin>>u>>v>>w;
            edge[all_e].s=edge[all_e+1].e=u;
            edge[all_e].e=edge[all_e+1].s=v;
            edge[all_e++].t=w;
            edge[all_e++].t=w;               //由于paths的双向性,两个方向权值相等,注意指针的移动
        }

		/*read in Negative Wormholds*/

        for(int j=1;j<=W_h;j++)
        {
            cin>>u>>v>>w;
            edge[all_e].s=u;
            edge[all_e].e=v;
            edge[all_e++].t=-w;     //注意权值为负
        }

		/*Bellman-Ford Algorithm*/

        if(bellman())
            cout<<"YES"<<endl;
        else
            cout<<"NO"<<endl;
	}
	return 0;
}


 

  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值