D117 最短路→差分约束 SPFA 算法 UVA1723 Intervals 区间
D117 最短路→差分约束 SPFA 算法 UVA1723 Intervals 区间_哔哩哔哩_bilibili
SP116 INTERVAL - 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]$

相关板子:
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]); } }
浙公网安备 33010602011771号