SW练习_POJ3259_黑洞_贝尔曼福德[模板]

参照:https://blog.csdn.net/qq_40674583/article/details/96632789

标准的贝尔曼福德

进行N-1次循环,松弛每一条边,如果还可以松弛,就说明有负

package com.company.POJ;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.StringTokenizer;
//SW练习_POJ3259_黑洞_贝尔曼福德
public class POJ32591116 {
    static List<Edge32591116> edges;
    static int N;
    public static void main(String[] args) throws Exception{
        BufferedReader reader=new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st=new StringTokenizer(reader.readLine());
        int T=Integer.parseInt(st.nextToken());//用例的个数
        for (int i = 0; i <T ; i++) {
            st=new StringTokenizer(reader.readLine());
            N=Integer.parseInt(st.nextToken());//农场数
            int M=Integer.parseInt(st.nextToken());//双向道路数
            int W=Integer.parseInt(st.nextToken());//黑洞数
            edges=new ArrayList<Edge32591116>();
            for (int j = 0; j <M ; j++) {
                st=new StringTokenizer(reader.readLine());
                int s=Integer.parseInt(st.nextToken());//开始节点
                int e=Integer.parseInt(st.nextToken());//结束节点
                int t=Integer.parseInt(st.nextToken());//消耗时间
                edges.add(new Edge32591116(s,e,t));
                edges.add(new Edge32591116(e,s,t));
            }
            for (int j = 0; j <W ; j++) {
                st=new StringTokenizer(reader.readLine());
                int s=Integer.parseInt(st.nextToken());//开始节点
                int e=Integer.parseInt(st.nextToken());//结束节点
                int t=Integer.parseInt(st.nextToken());//缩短的时间
                edges.add(new Edge32591116(s,e,-t));
            }
            System.out.printf("%s\n",process_bell_ford(edges,1));
        }
        reader.close();
    }
    public static String process_bell_ford(List<Edge32591116> edges,int start){
        int[] len=new int[N+1];
        Arrays.fill(len,1087654321);
        len[start]=0;
        for (int i = 1; i <N ; i++) {
            for (Edge32591116 edge:edges) {
                if(len[edge.end] >len[edge.from]+edge.time){
                    len[edge.end] =len[edge.from]+edge.time;
                }
            }
        }
        for (Edge32591116 edge:edges) {
            if(len[edge.end] >len[edge.from]+edge.time){
                //len[edge.end] =len[edge.from]+edge.time;
                return "YES";
            }
        }
        return "NO";
    }
    static class Edge32591116{
        int from;
        int end;
        int time;
        public Edge32591116(int from, int end, int time) {
            this.from = from;
            this.end = end;
            this.time = time;
        }
    }
}

 

package info.frady.poj;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.*;
import java.util.Vector;

/**
 * meng3.wei 2020.04.30
 2
 3 3 1
 1 2 2
 1 3 4
 2 3 1
 3 1 3
 3 2 1
 1 2 3
 2 3 4
 3 1 8
 NO
 YES
 */
public class POJ3259 {//Main
    static String [] result;
    static List<Egge3259>[] lists;
    static int N,M,W;

    public static int dis[];//存放起点到当前顶点的距离
    public static int pid[];//存放当前节点的父亲节点,这个题目不需要求这个
    public static int cnt[];//存放每个点被加入队列的次数,用于检查负环(如果一个点被放入了N次,肯定是有负环)
    public static boolean inq[];//保存某点是否加入队列
    public static LinkedList<Integer> li;//待访问的队列

    public static void main(String[] args) throws Exception{
        BufferedReader reader=new BufferedReader(new InputStreamReader(System.in));
        int T=Integer.parseInt(reader.readLine());
        result=new String[T];
        for (int i = 0; i < T; i++) {
            String str[]=reader.readLine().split(" ");
            N=Integer.parseInt(str[0]);//农场的个数
            M=Integer.parseInt(str[1]);//通道的个数
            W=Integer.parseInt(str[2]);//黑洞的个数
            lists=new ArrayList[N+1];
            for (int j = 0; j <N+1 ; j++) {
                lists[j]=new ArrayList<Egge3259>();
            }
            for (int j = 0; j < M; j++) {
                str=reader.readLine().split(" ");
                int start=Integer.parseInt(str[0]);
                int end=Integer.parseInt(str[1]);
                int len=Integer.parseInt(str[2]);
                lists[start].add(new Egge3259(start,end,len));
                lists[end].add(new Egge3259(end,start,len));
            }
            for (int j = 0; j < W; j++) {
                str=reader.readLine().split(" ");
                int start=Integer.parseInt(str[0]);
                int end=Integer.parseInt(str[1]);
                int len=Integer.parseInt(str[2]);
                lists[start].add(new Egge3259(start,end,-len));
            }
            result[i]=bellean_ford(1);
        }

        for (int i = 0; i <T ; i++) {
            System.out.println(result[i]);
        }
        reader.close();
    }


    private static String bellean_ford(int s) {
        dis=new int[N+1];
        pid=new int[N+1];
        cnt=new int[N+1];
        inq=new boolean[N+1];
        Arrays.fill(dis,Integer.MAX_VALUE);
        li=new LinkedList<Integer>();
        li.add(s);
        inq[s]=true;
        dis[s]=0;
        while(!li.isEmpty()){
            int start=li.pop();
            inq[start]=false;
            //for (int i = 0; i <lists[start].size() ; i++) {
            for(Egge3259 e : lists[start]){ //遍历每一个连接的边
                if( dis[e.end] > dis[start]+e.distance){从start中转到end的距离
                    dis[e.end]=dis[start]+e.distance;
                    pid[e.end]=start;
                    if(!inq[e.end]){
                        li.add(e.end);
                        inq[e.end]=true;
                        cnt[e.end]=cnt[e.end]+1;
                        if(cnt[e.end]>N){
                            return "YES";
                        }

                    }
                }
            }

        }

        return "NO";//没有负环路
    }
}
class Egge3259{
    int start;
    int end;
    int distance;
    public Egge3259(int start,int end,int distance){
        this.start=start;
        this.end=end;
        this.distance=distance;
    }
}

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值