当前位置: 代码迷 >> 综合 >> poj 1275 Cashier Employment 差分约束
  详细解决方案

poj 1275 Cashier Employment 差分约束

热度:29   发布时间:2024-01-19 05:44:42.0

差分约束模板题,差分约束是判断联立不等式组是否有解的一种方法,建图是关键。

代码:

//poj 1275
//sep9
#include <iostream>
#include <queue>
using namespace std;
const int maxM=10024;
const int maxN=32;struct Edge
{int v,w,nxt;	
}edge[maxM];
int t[maxN],c[maxN],head[maxN],vis[maxN],inq[maxN],dis[maxN];
int e;void addedge(int u,int v,int w)
{edge[e].v=v;edge[e].w=w;edge[e].nxt=head[u];head[u]=e++;	
}bool spfa()
{memset(inq,0,sizeof(inq));for(int i=0;i<=24;++i) dis[i]=INT_MIN;memset(vis,0,sizeof(vis));queue<int> Q;Q.push(0);dis[0]=0;inq[0]=1;vis[0]=1;while(!Q.empty()){int u=Q.front();Q.pop();inq[u]=0;for(int i=head[u];i!=-1;i=edge[i].nxt){int v=edge[i].v,w=edge[i].w;if(dis[v]<dis[u]+w){dis[v]=dis[u]+w;if(inq[v]==0){Q.push(v);++vis[v];inq[v]=1;if(vis[v]>=25)return false;}	}}}	return true;
}int main()
{int cases;scanf("%d",&cases);while(cases--){memset(head,-1,sizeof(head));memset(t,0,sizeof(t));for(int i=1;i<=24;++i)scanf("%d",&c[i]);int n;scanf("%d",&n);	for(int i=0;i<n;++i){int x;scanf("%d",&x);++t[x+1];}int l=0,r=n+1,ans=-1,mid;while(l<r){mid=(l+r)/2;memset(head,-1,sizeof(head));e=0;for(int i=0;i<24;++i){addedge(i,i+1,0);		addedge(i+1,i,-t[i+1]);}addedge(0,24,mid);for(int j=1;j<=24;++j){int i=j+8;if(i<=24)addedge(j,i,c[i]);else{i=j+8-24;addedge(j,i,c[i]-mid);		}}if(spfa()){ans=mid;r=mid;}else{l=mid+1;}}if(ans!=-1)printf("%d\n",ans);elseputs("No Solution");		}return 0;	
}