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;
}