POJ3169 Layout ( 差分约束 | 最短路 )

文章目录

题目连接 poj or vj

题意

第一行的三个数, 共有n头牛,有ml个关系好的牛的信息,有md个关系不好的牛的信息,

接下来ml行,每行三个数 A, B, D, 表示 A牛 和 B牛 相距不希望超过 D,

接下来md行,每行三个数 A, B, D 表示 A牛 和 B牛 的相距至少要有 D

求 1号牛 到 n号牛 的远距离, 如果距离无限大输出-2,如果无解输出-1。

题解

好感:                d[ j ] - d[ i ] <= len

反感: d[ j ] - d[ i ] >= len -------->> d[ i ] - d[ j ] <= - len

由此, 可以建立差分约束系统, 利用 spfa 来判负环, 对应输出

在这里插入图片描述

在这里插入图片描述

图片来自此大佬, 思路非常清晰, 点赞

代码

// #include <bits/stdc++.h> 
#include <cstdio>
#include <cstring>
#include <queue>
using namespace std; 
#define rg register 
#define sc scanf 
#define pf printf 
typedef long long ll; 

class SPFA_judgeLoop {
public:
	static const int MAXN = 1e3+10;
	static const int MAXM = 2e4+10;
    static const int INF = 0x3f3f3f3f; // 可能会小
	int n, m, s;
	struct EDGE {
		int v, w, to;
	}e[MAXM];
	int head[MAXN], cnt, dis[MAXN]; bool vis[MAXN];
	inline void add ( int u, int v, int w ) {
		e[cnt].v = v, e[cnt].w = w, e[cnt].to = head[u]; head[u] = cnt++; 
	}
	int tim[MAXN];
	queue<int> q;
	void ini ( int n, int m, int s ) { 
		this->n = n; this->m =m, this->s = s;
		cnt = 0;
		memset ( head, -1, sizeof ( head ) );
		memset ( dis, 0x3f, sizeof ( dis ) );
		dis[s] = 0;
		memset ( vis, false, sizeof ( vis ) );
		while ( !q.empty ( ) ) q.pop ( );
		memset ( tim, 0, sizeof (tim) );
	}
	bool run ( ) {
		q.push( s );
		vis[s] = true;
		tim[s] = 0;
		while ( !q.empty ( ) ) {
			int u = q.front ( );
			q.pop ( );
			vis[u] = false;
			for ( int k = head[u]; k!=-1; k = e[k].to ) {
				int v = e[k].v, w = e[k].w;
				if ( dis[v] > dis[u]+w ) {
					dis[v] = dis[u]+w;
					tim[v] = tim[u]+1;
					if ( tim[v] >= n ) {
						return true;
					}
					if ( !vis[v] ) q.push ( v ), vis[v] = true;
				}
			}
		}
		return false;
	}
}sp;

int main ( ) {  // freopen( "F:\\in\\.txt" , "r" , stdin ); 

    int N, ML, MD,
        u, v, w;

    sc( "%d%d%d" , &N , &ML , &MD );


    sp.ini( N, ML+MD, 1 );

    for ( int i = 0 ; i < ML ; ++i ) { 
        sc( "%d%d%d" , &u , &v , &w ) ; 
        sp.add( u , v , w ) ; 
    }

    for ( int i = 0 ; i < MD ; ++i ) { 
        sc( "%d%d%d" , &u , &v , &w ) ; 
        sp.add( v , u , -w ) ; 
    }

    if ( sp.run() ) {
        puts( "-1" );
    } else {
        ( sp.dis[N]==sp.INF )? puts("-2") : pf( "%d\n" , sp.dis[N] ) ; 
    }


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值