POJ - 3259 Wormholes解题报告(Bellman-Ford判断有向图中是否有负权环)

题目大意:

一个有向图,给你n个点,m条双向路径,以及t条虫洞。每条路径描述在两个点ab之间移动需要时间v。每条虫洞描述从a到b需要时间-v(类似于时空穿越)。现在就问你,一个人能否从某个点开始,通过若干次虫洞和路径,在他出发之前的每个时刻回到出发点。注意:两个点之间有可能有多条路径!

分析:

相当于找一个有向图中的负权回路。关于两个点之间可能有多条路径这个事情,在存图的时候要好好考虑一下。比如两个点AB之间有两条路径a,b(va>vb)以及一条虫洞单向c,那么,为了形成负权环路,我的存储方式应该是:map [ A ] [ B ] = – vc ; map [ B ] [ A ] = vb; 因为如果某条负权回路经过边a,那么,那这条边改成b也一定是负权回路(va>vb),如果经过b,那么,把这条边改成c也一定是负权回路(vb>0>-vc)。所以我选择先把合适的值存到map数组里,在遍历map数组来得到所有的有向边。时间复杂度: O(n2)

代码:

#include<iostream>
#include<string.h>
#define inf 0x3f3f3f3f

using namespace std;
struct edge
{
    int s;
    int e;
    int v;
}l[2600]={0};

int num=1;
int map[550][550];
int n,m,t;
int flag=0;

void my_Bellman_Ford()
{
    int dis[550]={0};
    dis[1]=0;
    flag=0;
    for(int k=1;k<n;k++)
    {
        for(int i=1;i<=num;i++)
        {
            if(dis[l[i].e]>dis[l[i].s]+l[i].v)
            {
                dis[l[i].e]=dis[l[i].s]+l[i].v;
            }
        }
    }
    for(int i=1;i<=num;i++)
    {
        if(dis[l[i].e]>dis[l[i].s]+l[i].v)
        {
            flag=1;
            return;
        }
    }
}

int main()
{
    int test;
    cin>>test;
    while(test--)
    {
        cin>>n>>m>>t;
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=n;j++)
            {
                map[i][j]=inf;
            }
        }
        int ls,le,lv;
        for(int i=1;i<=m;i++)
        {

            cin>>ls>>le>>lv;
            if(map[ls][le]>lv)
            { 
                map[ls][le]=lv;
                map[le][ls]=lv;
            }
        }
        for(int i=1;i<=t;i++)
        {
            cin>>ls>>le>>lv;
            map[ls][le]=-lv;
        }
        num=1;
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=n;j++)
            {
                if(map[i][j]!=inf)
                {
                    l[num].s=i;
                    l[num].e=j;
                    l[num].v=map[i][j];
                    num++;
                }
            }
        }
        num--;
        my_Bellman_Ford();
        if(flag==1)cout<<"YES"<<endl;
        else cout<<"NO"<<endl;
    }
}

后记:

这道题本来是训练计划里的一道,当时并没做出来,然后就莫名其妙给忘记了,现在回来一看,突然感觉简单了好多。变强中···

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