D117 最短路→差分约束 SPFA 算法 UVA1723 Intervals 区间

D117 最短路→差分约束 SPFA 算法 UVA1723 Intervals 区间_哔哩哔哩_bilibili

 

SP116 INTERVAL - Intervals - 洛谷

UVA1723 Intervals - 洛谷

给 n 个约束条件,求最小解。

思路

在区间 $[a,b​]$ 中至少取任意互不相同的 $c$ 个整数,即 $f[a,b]\ge c$

设前缀和 $s[i]$ 表示 $[1,i]$ 中选数的个数,$s[0] = 0$

1. $[1,i]$ 内选数与 $[1,i-1]$ 内选数相等或多一个,即 $s[i]-s[i-1]\ge 0$ 且 $s[i]-s[i-1]\le 1$

2. $[a,b]$ 内选数应大于等于 $c$,即 $s[b]-s[a-1]\ge c$

题目 $a$ 和 $b$ 的值可以取 0,为了用前缀和,让 $a$ 和 $b$ 都加 1,范围变成 1~50001

因为求最小解,把不等式均变成 $\ge$,把变量 $s[i]$ 看做点,点的编号是下标 $i$,连边建图

从第一个 add 可知,0 点就是超级源点(0边权可达各点),所以从 0 点开始跑最长路,答案是 $d[50001]$

image

相关板子:

D116【模板】最短路→差分约束 SPFA 算法 P5960 差分约束 - 董晓 - 博客园

 

// 差分约束 SPFA 算法 O(NM)
#include<bits/stdc++.h>
using namespace std;

const int N=50005,M=N*3;
int h[N],to[M],ww[M],ne[M],idx;
void add(int a,int b,int c){
  to[++idx]=b,ww[idx]=c,ne[idx]=h[a],h[a]=idx;
}
int n,d[N];
bool vis[N];

void spfa(){
  memset(d,-0x3f,sizeof d); d[0]=0;
  queue<int> q; q.push(0); vis[0]=true;
  while(!q.empty()){
    int u=q.front(); q.pop(); vis[u]=false;
    for(int i=h[u]; i; i=ne[i]){
      int v=to[i];
      if(d[v]<d[u]+ww[i]){ //最长路
        d[v]=d[u]+ww[i];
        if(!vis[v]) q.push(v),vis[v]=true;
      }
    }
  }
}
int main(){
  int T; scanf("%d",&T);
  while(T--){
    scanf("%d",&n);
    idx=0; memset(h,0,sizeof h);
    for(int i=1; i<N; i++){
      add(i-1,i,0);  //i-(i-1)>=0
      add(i,i-1,-1); //(i-1)-i>=-1
    }
    for(int i=1,a,b,c; i<=n; i++){
      scanf("%d%d%d",&a,&b,&c);
      a++,b++;
      add(a-1,b,c); //b-(a-1)>=c
    }
    
    spfa();
    printf("%d\n",d[50001]);
  }
}

 

posted @ 2026-03-30 19:30  董晓  阅读(97)  评论(0)    收藏  举报