AcWing 1170 排队布局

该博客介绍了如何使用差分约束和最短路算法解决一个有趣的奶牛排队问题。在给定奶牛编号、好感与反感距离限制的情况下,判断并计算1号奶牛与N号奶牛间可能的最大距离。分析了最短路图中负环、正环与无环对解的存在性与有限性的关系,并提供了相应的代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目描述:

当排队等候喂食时,奶牛喜欢和它们的朋友站得靠近些。

农夫约翰有 N 头奶牛,编号从 1 到 N,沿一条直线站着等候喂食。

奶牛排在队伍中的顺序和它们的编号是相同的。

因为奶牛相当苗条,所以可能有两头或者更多奶牛站在同一位置上。

如果我们想象奶牛是站在一条数轴上的话,允许有两头或更多奶牛拥有相同的横坐标。

一些奶牛相互间存有好感,它们希望两者之间的距离不超过一个给定的数 L。

另一方面,一些奶牛相互间非常反感,它们希望两者间的距离不小于一个给定的数 D。

给出 ML 条关于两头奶牛间有好感的描述,再给出 MD 条关于两头奶牛间存有反感的描述。

你的工作是:如果不存在满足要求的方案,输出-1;如果 1 号奶牛和 N 号奶牛间的距离可以任意大,输出-2;否则,计算出在满足所有要求的情况下,1 号奶牛和 N 号奶牛间可能的最大距离。

输入格式

第一行包含三个整数 N,ML,MD。

接下来 ML 行,每行包含三个正整数 A,B,L,表示奶牛 A 和奶牛 B 至多相隔 L 的距离。

再接下来 MD 行,每行包含三个正整数 A,B,D,表示奶牛 A 和奶牛 B 至少相隔 D 的距离。

输出格式

输出一个整数,如果不存在满足要求的方案,输出-1;如果 1 号奶牛和 N 号奶牛间的距离可以任意大,输出-2;否则,输出在满足所有要求的情况下,1 号奶牛和 N 号奶牛间可能的最大距离。

数据范围

2≤N≤1000,
11≤ML,MD≤10^4,
1≤L,D≤10^6

输入样例:

4 2 1
1 3 10
2 4 20
2 3 3

输出样例:

27

分析:

 本题同样是差分约束的问题,要求1到n之间可能的最大的距离,这使得我们更加深刻的理解了差分约束的思想。在AcWing 1169 糖果里,仔细的讲解了差分约束的基本思想,以及求不等式组的最大解需要求最短路,求最小解需要求最长路,这里不等式解的最大最小都是相对而言的。比如a2 <= a1 + 1,a3 <= a2 + 1,求最短路和最长路的建图如下图所示:

对于最短路而言,设起点a1 = 0,求得a2的最大值是1,a3的最大值是2;对于最长路而言,设a3 = 0,则a2的最小值是-1,a1的最小值是-2,所以所谓的最值都是相对的,本题求1到n之间的最大距离很能够体现这种相对的关系。下面梳理下已知的结论:对于同一个不等式组,最短路和最长路建图是完全不同的,边的大小互为相反数,方向相反,如果不等式组无解,即没有合法的一组解使得所有的不等式都成立,那么建立的最短路图中一定存在负环,建立的最长路的图中一定存在正环。如果不等式组有解,最短路求得的是最大解,最长路求得的是最小解。

要求1到n之间的距离,不妨设1号点的坐标就是0,从0出发到达终点n,要想距离最大,则n号点的解就要最大,所以需要求最短路。当然如果将n的坐标设置为0,也可以通过求最长路来使得1到n之间的距离最大。本题的约束条件有三个,ai-1 <= ai;ai - aj <= L;ai - aj >= D。暂且不去分析具体的约束条件,先讨论一个问题,什么情况下起点到终点的距离可以无限大。关于这个问题,很多博客仅仅给出了必要条件,比如说从起点到达不了终点,图中的两点间没有可达的路径,没有约束距离就无限大,但这仅仅是必要条件而非充分条件。比如下面的不等式组:a1 <= a2 - 1,a2 <= a3 - 1,最短路建图如下:

从a3是可以到达a1的,图中没有孤立的点,a3 = 0时,a1就可以无限小,他们的距离就无限大。这个简单的例子可以看出,差分约束的不等式组对应的图如果没有环,起点和终点的距离是可以无限大的。要想两点间距离有限,需要图中有一个适当的环,来约束解的范围。上图的不等式组可以推出a1 <= a3 - 2,那么我再加上一个不等式约束a1 >= a3 - 4,,就成功的将a1到a3之间的距离限制在4个单位以内了。对应图中的表现不过是a1到a3连一条边权为4的边,我们分析此时环的长度4 - 1 - 1 = 2是大于0的。所以我们可以得出下面的结论:最短路的图中如果存在负环,差分约束问题无合法解,如果存在正环,则正环上任意两点间的距离都是有限的,不存在环的图上任意两点间的距离都可以是无限大的。这个结论可以类比到最长路的图中。换一种表达形式的话就是如果要图中的两点间距离有限,只需要存在一个正环,且这两个点都在环上。那么本题我们是否需要判断了负环还要判断正环呢?实际上是不需要的。

第一个约束条件ai >= ai-1,构建的最短路图中an可以到达an-1,an-1可以到达an-2,...。所以an可以到达每一点,包括a1。我们先以an为起点,求一遍最短路,如果存在负环,则不等式组无解,如果不存在负环,那么不等式组肯定有解,下面要判断的就是an - a1的结果是否可以无限大。在确定了不等式组有解的情况下,我们以a1为起点再求一遍最短路,当然a1不一定能够到达每一点,如果a1到达不了an,说明不存在一个环,环上同时包含a1到an。如果a1出发可以到达an,则一定存在由a1、an构成的正环。从ai出发可以到达an,an出发可以到达a1,这个条件保证了环的存在。第一次以an为起点求最短路时不存在负环,说明这个环一定不是负环,那么就是正环了(即使环的长度为0也是有解的)。根据我们上一段推出的结论可知,此时a1和an之间的距离是有限的,并且第二次求最短路过程中a1是起点,求得的an是最大值,所以此时的an就是我们要求的最大距离了。

最后再总结下本题给我们的经验(仅仅是个人经验总结)。最短路存在负环,差分约束问题无解,最短路存在正环,环上任意两点之间距离有限,最短路不存在环,任意两点间距离可以是无穷大;最长路存在正环,差分约束问题无解,最长路存在负环,环上任意两点之间距离有限,最长路不存在环,任意两点间距离可以是无穷大。总的代码如下:

#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
const int N = 1005,M = 21005;
int idx,h[N],e[M],ne[M],w[M];
int n,cnt[N],d[N],q[N];
bool st[N];
void add(int a,int b,int c){
    e[idx] = b,w[idx] = c,ne[idx] = h[a],h[a] = idx++;
}
bool spfa(int s){
    memset(cnt,0,sizeof cnt);
    memset(st,false,sizeof st);
    memset(d,0x3f,sizeof d);
    d[s] = 0;
    q[0] = s;
    st[s] = true;
    int hh = 0,tt = 1;
    while(hh != tt){
        int u = q[hh++];
        st[u] = false;
        if(hh == N) hh = 0;
        for(int i = h[u];~i;i = ne[i]){
            int j = e[i];
            if(d[j] > d[u] + w[i]){
                d[j] = d[u] + w[i];
                cnt[j] = cnt[u] + 1;
                if(cnt[j] >= n) return false;;
                if(!st[j]){
                    st[j] = true;
                    q[tt++] = j;
                    if(tt == N) tt = 0;
                }
            }
        }
    }
    return true;
}
int main(){
    int ml,md,a,b,l;
    scanf("%d%d%d",&n,&ml,&md);
    memset(h,-1,sizeof h);
    for(int i = 2;i <= n;i++){
        add(i,i - 1,0);//最短路建图
    }
    while(ml--){
        scanf("%d%d%d",&a,&b,&l);
        if(a > b)   swap(a,b);
        add(a,b,l);
    }
    while(md--){
        scanf("%d%d%d",&a,&b,&l);
        if(a > b)   swap(a,b);
        add(b,a,-l);
    }
    if(!spfa(n))    puts("-1");//从n出发,存在负环,不等式无解
    else{
        spfa(1);
        if(d[n] == 0x3f3f3f3f)   puts("-2");//从1出发不能到达n,距离无限制
        else    printf("%d\n",d[n]);//存在正环,距离有限
    }
    return 0;
}

 

### 关于 AcWing 1302 的解析 目前提供的引用内容并未直接提及 AcWing 平台上的第 1302 题的具体信息。然而,通过分析已知的引用材料以及常见的算法竞赛题目类型,可以推测该题可能涉及某些特定的算法领域,例如递归、贪心、二分查找或其他经典问题。 #### 可能的方向与背景 AcWing 平台上编为 1302 的题目通常会属于某一类经典的编程挑战,比如字符串处理、动态规划、图论或者数学问题。由于具体题目描述未提供,以下是基于常见算法竞赛类型的假设性解析: --- #### **假设方向一:字符串匹配** 如果 AcWing 1302 涉及字符串匹配,则可能需要使用 KMP 算法或 Z 函数来解决模式串在主串中的位置问题。KMP 算法的时间复杂度为 \(O(n+m)\),其中 \(n\) 和 \(m\) 分别为主串和模式串长度[^1]。 ```python def compute_lps(pattern): m = len(pattern) lps = [0] * m j = 0 for i in range(1, m): while j > 0 and pattern[i] != pattern[j]: j = lps[j - 1] if pattern[i] == pattern[j]: j += 1 lps[i] = j return lps def kmp_search(text, pattern): n, m = len(text), len(pattern) lps = compute_lps(pattern) matches = [] j = 0 for i in range(n): while j > 0 and text[i] != pattern[j]: j = lps[j - 1] if text[i] == pattern[j]: j += 1 if j == m: matches.append(i - m + 1) j = lps[j - 1] return matches ``` --- #### **假设方向二:贪心策略** 若 AcWing 1302 属于贪心问题,则需找到局部最优解并逐步扩展至全局最优解。例如,在分配资源或选择区间覆盖的情况下,可以通过排序加迭代的方式解决问题[^4]。 ```python def greedy_interval_selection(intervals): intervals.sort(key=lambda x: x[1]) # 按结束时间升序排列 count = 0 end_time = float('-inf') for interval in intervals: if interval[0] >= end_time: count += 1 end_time = interval[1] return count ``` --- #### **假设方向三:二分查找** 当 AcWing 1302 涉及数值范围内的目标值定位时,可采用二分查找方法降低时间复杂度。以下是一个通用的整数二分模板[^5]: ```python def binary_search(q, target): l, r = 0, len(q) - 1 while l < r: mid = (l + r) >> 1 if q[mid] < target: l = mid + 1 else: r = mid return l if q[l] == target else -1 ``` --- ### 总结 尽管当前无法确切得知 AcWing 1302 的具体内容,但从已有引用资料来看,其解决方案很可能依赖于上述提到的经典算法之一。建议访问 AcWing 官网查看官方题解或社区讨论区获取更详细的解答。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值