【刷题】【差分约束】出纳员问题
调了一下午,已经没有力气写题解了,
wa点已经标出来了,
#include<cstdio> #include<cstdlib> #include<cstring> #include<queue> using namespace std; int n,x; const int N=28,M=120; int nd[N],c[N]; int tot,head[N]; int ev[M],ew[M],enx[M]; void add(int u,int v,int w) { ev[++tot]=v,ew[tot]=w,enx[tot]=head[u],head[u]=tot; } void build(int as) { tot=0; memset(head,0,sizeof(head)); add(0,24,as); for(int i=1;i<=24;i++) { add(i-1,i,0); add(i,i-1,-c[i]); if(i>=9) add(i-8,i,nd[i]); if(i<=8) add(i+16,i,nd[i]-as); } } int dis[N],tm[N]; bool in[N]; bool spfa(int mx) { build(mx); memset(dis,0x80,sizeof(dis)); memset(in,false,sizeof(in)); memset(tm,0,sizeof(tm)); queue <int> q; while(!q.empty() ) q.pop() ; q.push(0);dis[0]=0; int cnt=-1; while(!q.empty() && dis[24]<=mx) { int t=q.front() ;q.pop() ; for(int i=head[t];i;i=enx[i]) { int nx=ev[i]; if(dis[nx]<dis[t]+ew[i]) { dis[nx]=dis[t]+ew[i]; if(++tm[nx]>=25) return false; if(!in[nx]) in[nx]=true,q.push(nx); } } in[t]=false; } return dis[24]==mx; } int main() { int T; scanf("%d",&T); while(T--) { for(int i=1;i<=24;i++) scanf("%d",&nd[i]);//nd[i]表示i-1 ~ i需要的人数 memset(c,0,sizeof(c)); scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%d",&x),c[x+1]++;//x 开始投入工作 第一次工作在x-x+1,就是c[x+1] int ans=n+1; for(int i=0;i<=n;i++) if(spfa(i)) { ans=i; break; } if(ans>n) printf("No Solution\n"); else printf("%d\n",ans); } return 0; }