题目链接
题意大概就是给我们
n
n
n个营地,
c
[
i
]
c[i]
c[i]表示第
i
i
i个营地最多的人数,第
u
u
u-第
v
v
v个营地一共有
w
w
w个人。问最少有多少人。
对于这种题型,我们一般做法是首先确定一个数组表示前面
i
i
i个营地的总人数
挖掘隐藏条件,每一个营地的人数不可能为负数,所以 a [ i ] − a [ i − 1 ] ≥ 0 a[i]-a[i-1]\geq0 a[i]−a[i−1]≥0
每个营地最多有 i i i人,我们可以知道, a [ i ] − a [ i − 1 ] ≤ c [ i ] a[i]-a[i-1]\leq c[i] a[i]−a[i−1]≤c[i]
u − v u-v u−v一共最少有 w w w人,我们可以得出, a [ u ] − a [ v − 1 ] ≥ w a[u]-a[v-1]\geq w a[u]−a[v−1]≥w
我们可以把第二个条件化简为
a
[
i
]
−
a
[
i
−
1
]
≤
a
[
i
]
→
a
[
i
−
1
]
−
a
[
i
]
≥
−
c
[
i
]
a[i]-a[i-1]\leq a[i] \rightarrow a[i-1]-a[i] \geq -c[i]
a[i]−a[i−1]≤a[i]→a[i−1]−a[i]≥−c[i]
由上化简,我们就把所有的代数式换成了大于等于的形式,开始建图了
题目要求的是最小的人数,那么也就是
m
i
n
(
a
[
n
]
−
a
[
0
]
)
min(a[n]-a[0])
min(a[n]−a[0])那么我们就可以这么建图:
我们按照从被减数向减数建一条边,边权为右边的值。
这样建图有什么好处?因为我们要求的是
m
i
n
(
a
[
n
]
−
a
[
0
]
)
min(a[n]-a[0])
min(a[n]−a[0]),而我们这么建图就会使源点
0
0
0到达的任意一个
v
v
v最长路长度都是最少的人数,为什么是最长路?大于等于符号决定的呀,当大于等于时,只有最长路不会和其他方向的边冲突,小于等于时,我们只有最短路不会和其他方式的边冲突。
接下来看代码,spfa版本
#include<stdio.h>
#include<algorithm>
#include<string.h>
//#include<windows.h>
using namespace std;
const int N = 2e5+5;
int deq[N*2],a[N],head[N],tot=0;
struct ED
{
int pre,to,w;
}ed[2*N];
int vis[N],dis[N],num[N];
void spfa(int x){
memset(dis,-1,sizeof dis);
memset(vis,0,sizeof vis);
memset(deq,0,sizeof deq);
memset(num,0,sizeof num);
dis[0]=0;
int l=1,r=0;
deq[++r]=0;
while(l<=r){
int u=deq[l];
l++;
vis[u]=0;
//printf("%dsss\n",u);
for(int i=head[u];~i;i=ed[i].pre){
int v=ed[i].to;
//printf("%d %d %d %d %d\n",u,v,dis[u],ed[i].w,dis[v]);
if(dis[v]<dis[u]+ed[i].w) {
dis[v]=dis[u]+ed[i].w;
if(vis[v]) continue;
deq[++r]=v;
num[v]++;
if(num[v]>=x) {
printf("Bad Estimations\n");
return ;
}
vis[v]=1;
//printf("%d %d\n",u,v);
}
}
}
if(dis[x]==-1){
printf("Bad Estimations\n");
}
else {
printf("%d\n",dis[x]);
}
}
void add(int u,int v,int w){
ed[++tot].pre=head[u];
ed[tot].to=v;
ed[tot].w=w;
head[u]=tot;
}
int main(){
int n,m,i,j,k;
while (scanf("%d %d",&n,&m)==2)
{
tot=0;
for(i=0;i<=n;i++){
head[i]=-1;
}
for(i=1;i<=n;i++){
scanf("%d",&a[i]);
add(i-1,i,0);
add(i,i-1,-a[i]);
}
int u,v,w;
for(i=1;i<=m;i++){
scanf("%d %d %d",&u,&v,&w);
add(u-1,v,w);
}
spfa(n);
}
//system("pause");
}