#315 虫洞 判负权回路(bmf/spfa)

题目描述
在一个神秘岛上,有N(1 <= N <= 500)个洞口,标号1..N,它们之间有M (1 <= M <= 2500) 条通道相连。

神秘的竟然另外还有W (1 <= W <=200)条传说中的时间虫洞—-当到达通道的另一端洞口时,竟然可以比进入的时间要早!

你当然想进行这样的时间之旅,希望从一个洞口s出发,经过几个通道,在比出发早些时候的时间回到洞口s。也许还能碰到自己呢,hehe 根据给定的地图,请判断能否实现这样的愿望。

输入格式
第一行:一个整数 F (1 <= F <= 5),表示共有F组数据。(多组数据测试)

每组数据: 第1行:三个整数 N M W

第2至M+1行:每行三个整数 (S, E, T),表示在S与E洞口之间有一个双向通道,通过需要T(0 <= T <= 10,000) 秒。

第M+2至M+W+1行:每行三个整数 (S, E, T),表示在S与E洞口之间有一个单向通道,从S到E可以回到之前T(0 <= T <= 10,000) 秒。

输出格式
共1..F行,每行对应一组数据,如果可以实现愿望输出”YES”,否则输出”NO”.

①bellman-ford

若无负权回路,迭代n-1次可得出最短路。故若迭代n-1次仍未得出,即存在负权回路。

int bmf()
{
    memset(dis,10,sizeof(dis));
    dis[1]=0;
    for(int i=1;i<=n;++i)
    {
        int flag=0;
        for(int j=1;j<=m*2+w;++j)
            if(dis[e[j].q]+e[j].v<dis[e[j].z])   
                dis[e[j].z]=dis[e[j].q]+e[j].v;         
        if(!flag) return 0;//得出最短路即返回0,无负权回路。
    }//有可能迭代n-1次恰好得最短路,故i应循环n次才可判断。
    return 1;
}

②SPFA

两种思路。

1.因为最多迭代n-1次,故每个点最多被更新n-1次,即进队次数。若大于n-1,则存在负权回路。


void spfa()
{
    memset(in,0,sizeof(in));//进队次数
    memset(dis,10,sizeof(dis));
    memset(vis,0,sizeof(vis));
    flag=0;
    int head=0,tail=0;
    q[++tail]=1;
    in[1]=1;
    vis[1]=1;
    dis[1]=0;
    while(head++<tail)
    {
        for(int i=linkk[q[head]];i;i=e[i].next)
            if(dis[e[i].y]>dis[q[head]]+e[i].v)
            {
                dis[e[i].y]=dis[q[head]]+e[i].v;
                if(!vis[e[i].y]) {
                    q[++tail]=e[i].y;vis[e[i].y]=1;in[e[i].y]++;
                    if(in[e[i].y]==n){
                        flag=1;return;
                    }
                }
            }
        vis[q[head]]=0;
    }
}

2.最短路最多有n-1条路径。记录到某点的最短路包含的路径条数,若路径条数>n-1,即有负权回路。

void spfa()
{
    memset(vis,0,sizeof(vis));
    memset(path,0,sizeof(path));
    memset(dis,10,sizeof(dis));
    int head=0,tail=0;
    flag=0;
    q[++tail]=1;
    vis[1]=1;
    dis[1]=0;
    while(head++<tail)
    {
        for(int i=linkk[q[head]];i;i=e[i].next)
            if(dis[e[i].y]>dis[q[head]]+e[i].v)
            {
                path[e[i].y]=path[q[head]]+1;//若点A能更新点B,则源点至B路径条数为至A条数+1.
                dis[e[i].y]=dis[q[head]]+e[i].v;
                if(path[e[i].y]==n){
                    flag=1;return;
                }
                if(!vis[e[i].y]) q[++tail]=e[i].y,vis[e[i].y]=1;
            }
        vis[q[head]]=0;
    }
}

相较之下应是SPFA的第二种方法效率较高。因为若存在环,第一种思想将这个环跑了n遍方可得出。而第二种仅需跑一遍。


这题用SPFA坑好**多啊。多组数据,dis、vis、path、flag要初始化,邻接表的计数器和link也要初始化。
啊。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值