小 K 的农场

GitHub跳转原题关系图返回列表

把三类作物数量关系统一成差分约束边,并检测负环。

OJ: luogu

题目 ID: P1993

难度:普及+/提高-

标签:差分约束负环SPFApython

日期: 2026-07-17 03:00

题意

判断至少、至多、相等三类农场数量关系能否同时满足。

思路

全部改写为 x_v <= x_u+w:至少关系反向并取负权,至多关系按上界建边,相等建两条 0 边。所有点从 0 开始做最短路,出现负环即矛盾。

Python 知识

  • 不同长度操作行用 list(map(...)) 统一解析。
  • dequebytearray 是 SPFA 的常用组合。
  • 输出只取决于是否检测到负环。

代码

python
import sys
from collections import deque


input = sys.stdin.buffer.readline
n, constraints = map(int, input().split())
graph = [[] for _ in range(n + 1)]
for _ in range(constraints):
    operation = list(map(int, input().split()))
    if operation[0] == 1:
        _, a, b, c = operation
        graph[a].append((b, -c))
    elif operation[0] == 2:
        _, a, b, c = operation
        graph[b].append((a, c))
    else:
        _, a, b = operation
        graph[a].append((b, 0))
        graph[b].append((a, 0))

distance = [0] * (n + 1)
edge_count = [0] * (n + 1)
in_queue = bytearray(b"\x01") * (n + 1)
queue = deque(range(1, n + 1))
possible = True
while queue and possible:
    node = queue.popleft()
    in_queue[node] = 0
    for neighbor, weight in graph[node]:
        candidate = distance[node] + weight
        if candidate < distance[neighbor]:
            distance[neighbor] = candidate
            edge_count[neighbor] = edge_count[node] + 1
            if edge_count[neighbor] >= n:
                possible = False
                break
            if not in_queue[neighbor]:
                queue.append(neighbor)
                in_queue[neighbor] = 1
print("Yes" if possible else "No")

原有 C++ 版本仍保留:

cpp
/**
 * Author by Rainboy blog: https://rainboylv.com github: https://github.com/rainboylvx
 * rbook: -> https://rbook.roj.ac.cn  https://rbook2.roj.ac.cn
 * rainboy的学习导航网站: https://idx.roj.ac.cn
 * create_at: 2026-07-17 01:40
 * update_at: 2026-07-17 01:40
 */
#include <bits/stdc++.h>
using namespace std;

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    return 0;
}

复杂度

SPFA 最坏 O(nm),空间 O(n+m)

总结

文字中的至少/至多先移项,统一为一个松弛方向后更不容易建反边。