analysis
有點麻煩
這道題的題解在
數與圖的完美結合
-------淺析差分約束系統
華中師大一附中 馮威
這篇國集論文裏面有,這篇論文很不錯
還是說一下大概的思路(自己敲了半天也沒敲出來思路):
設num[i] 爲來應聘的在第i個小時開始工作的人數
r[i] 爲第i個小時至少需要的人數
x[i] 爲招到的在第i個小時開始工作的人數
根據題意有:
0 <= x[i] <= num[i]
x[i] + x[i-1] + …+ x[i-7] >= r[i] (題目中的連續工作8小時)
再設 s[i] = x[1] + … + x[i]
則有: s[i] – s[i-1] >= 0
s[i-1] – s[i] >= –num[i]
s[i] – s[i-8] >= r[i], 8 <= i <= 24
s[i] – s[i+16] >= r[i] – s[24], 1<= i <= 7
還需要添加一個隱藏不等式: s[24] – s[0] >= ans(枚舉的答案)
通過枚舉s[24],來檢測是否滿足條件(題目是求最小值,即求最長路,以0爲源點),每次跑完spfa後,就看算出來的s[24]和枚舉的是不是一樣就行,因爲spfa求出來的是當前約束條件下的最小值,於是只要從小到大枚舉ans和s[24]相等了就說明當前的最小值是ans
這道題有待消化(總覺得有哪裏沒弄懂,但又說不出來)
code
#include<bits/stdc++.h>
using namespace std;
#define loop(i,start,end) for(register int i=start;i<=end;++i)
#define clean(arry,num) memset(arry,num,sizeof(arry))
template<typename T>void read(T &x){
char r=getchar();T neg=1;x=0;
while(r>'9'||r<'0'){if(r=='-')neg=-1;r=getchar();}
while(r>='0'&&r<='9'){x=(x<<1)+(x<<3)+r-'0';r=getchar();}
x*=neg;
}
int T;
int R[50];
int num[50];
int n;
struct node{
int e;
int w;
int nxt;
}edge[50<<2];
int head[50];
int cnt=0;
inline void addl(int u,int v,int w){
edge[cnt].e=v;
edge[cnt].w=w;
edge[cnt].nxt=head[u];
head[u]=cnt++;
}
inline void buildgraph(int w){
clean(head,-1);
cnt=0;
addl(0,24,w);
loop(i,1,24){
addl(i-1,i,0);
addl(i,i-1,-num[i]);
if(i>=9)
addl(i-8,i,R[i]);
else if(i<=8)
addl(i+16,i,R[i]-w);
}
}
queue<int>q;
int dis[50];
bool insta[50];
int in[50];
bool spfa(int ans){
loop(i,1,40)
dis[i]=-0x3f3f3f3f;
clean(insta,false);
clean(in,0);
dis[0]=0;
++in[0];
q.push(0);
while(q.empty()==false){
int f=q.front();
q.pop();
insta[f]=false;
for(int i=head[f];i!=-1;i=edge[i].nxt){
int v=edge[i].e;
if(dis[v]<dis[f]+edge[i].w){
dis[v]=dis[f]+edge[i].w;
if(!insta[v]){
insta[v]=true;
q.push(v);
if(++in[v]>24){
while(q.empty()==false)
q.pop();
return false;
}
}
}
}
}
return (dis[24]==ans)?true:false;
}
int main(){
#ifndef ONLINE_JUDGE
freopen("datain.txt","r",stdin);
#endif
read(T);
while(T--){
clean(head,-1);
cnt=0;
loop(i,1,24)
read(R[i]);
read(n);
clean(num,0);
loop(i,1,n){
int ti;
read(ti);
++num[ti+1];
}
bool flag=false;
loop(i,0,n){
buildgraph(i);
if(spfa(i)){
printf("%d\n",i);
flag=true;
break;
}
}
if(!flag)
printf("No Solution\n");
}
return 0;
}