您的位置:首页 > 其它

hdu_5855_Less Time, More profit(二分+最大权闭合图)

2016-08-16 18:04 399 查看

题目链接:hdu_5855_Less Time, More profit

题意:

有n个工厂,每建一个工厂要花费vi,需要时间ti,然后有m个商店,每个商店需要在指定的k个工厂中进货,才能盈利,如果其中一个不在,都不能盈利,问在满足利润大于等于k的情况下的最少时间t,和在t时刻的最大利润

题解:

二分时间+网络流的最大权闭合图。比赛的时候搞了半天的题意才看懂,4点过才开始写网络流,然而没时间调试了。然后就GG了

#include<bits/stdc++.h>
#define mst(a,b) memset(a,b,sizeof(a));
#define F(i,a,b) for(int i=a;i<=b;++i)
using namespace std;

const int N=511,inf=~0U>>2,M=401000;
struct edge{int t,f;edge*nxt,*pair;}*g
,*d
,pool[M],*cur=pool;
struct ISAP{
int n,m,i,S,T,h
,gap
,maxflow;
void init(int ss,int tt){for(S=ss,T=tt,cur=pool,i=1;i<=T;i++)g[i]=d[i]=NULL,h[i]=gap[i]=0;}
void add(int s,int t,int f){
edge*p=cur++;p->t=t,p->f=f,p->nxt=g[s],g[s]=p;
p=cur++,p->t=s,p->f=0,p->nxt=g[t],g[t]=p;
g[s]->pair=g[t],g[t]->pair=g[s];
}
int sap(int v,int flow){
if(v==T)return flow;
int rec=0;
for(edge*p=d[v];p;p=p->nxt)if(h[v]==h[p->t]+1&&p->f){
int ret=sap(p->t,min(flow-rec,p->f));
p->f-=ret;p->pair->f+=ret;d[v]=p;
if((rec+=ret)==flow)return flow;
}
if(!(--gap[h[v]]))h[S]=T;
gap[++h[v]]++;d[v]=g[v];
return rec;
}
int get_ans(){
for(gap[maxflow=0]=T,i=1;i<=T;i++)d[i]=g[i];
while(h[S]<T)maxflow+=sap(S,inf);
return maxflow;
}
}G;

int t,n,m,l,L,R,ansf,ic=1,all;
struct pat{
int v,t;
}pt[201];
struct shop{
int v,k,vis[201];
}sp[201];

bool check(int x)
{
all=0;
G.init(1,405);
F(i,1,n)if(pt[i].t<=x)G.add(i+201,405,pt[i].v);
int vv[201];
mst(vv,0);
F(i,1,m)
{
int fg=1;
F(j,1,sp[i].k)
if(pt[sp[i].vis[j]].t>x)fg=0;
if(fg)vv[i]=1;
}
F(i,1,m)if(vv[i])G.add(1,i+1,sp[i].v);
F(i,1,m)if(vv[i])
{
all+=sp[i].v;
F(j,1,sp[i].k)G.add(i+1,sp[i].vis[j]+201,inf);
}
ansf=all-G.get_ans();
if(ansf>=l)return 1;
else return 0;
}

int main(){
scanf("%d",&t);
while(t--)
{
ansf=0,all=0;
L=1e9,R=0;
scanf("%d%d%d",&n,&m,&l);
F(i,1,n)scanf("%d%d",&pt[i].v,&pt[i].t),L=min(L,pt[i].t),R=max(R,pt[i].t);
F(i,1,m)
{
scanf("%d%d",&sp[i].v,&sp[i].k);
F(j,1,sp[i].k)scanf("%d",&sp[i].vis[j]);
}
int mid,ans=0;
while(L<=R)
{
mid=(L+R)>>1;
if(check(mid))R=(ans=mid)-1;
else L=mid+1;
}
check(ans);
if(ansf>=l)printf("Case #%d: %d %d\n",ic++,ans,ansf);
else printf("Case #%d: impossible\n",ic++);
}
}
View Code

 

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: