您的位置:首页 > 其它

【二分答案】【最大流】bzoj3993 [Sdoi2015]星际战争

2015-04-15 20:21 375 查看
二分Time,
S->炮[i]:Time*b[i]

炮[i]->机器人[i]:INF

机器人[i]->T:a[i]。

判断是否满流。

#include<cstdio>
#include<cstring>
#include<cmath>
#include<queue>
using namespace std;
#define N 51
#define EPS 0.000001
#define INF 2147483647.0
typedef double db;
queue<int>q;
int n,m,a
,b
,sumv;
bool can

;
int v[2*N*(N+1)],en,first[N*2+3],next[2*N*(N+1)];
db cap[2*N*(N+1)];
void AddEdge(int U,int V,db W)
{
v[en]=V; cap[en]=W; next[en]=first[U]; first[U]=en++;
v[en]=U; cap[en]=0; next[en]=first[V]; first[V]=en++;
}
int S,T,nn;
int d[N*2+3],cur[N*2+3];
bool bfs()
{
memset(d,-1,sizeof(int)*(nn+1));
d[S]=0;
q.push(S);
while(!q.empty())
{
int U=q.front(); q.pop();
for(int i=first[U];i!=-1;i=next[i])
if(d[v[i]]==-1&&cap[i]>EPS)
{
d[v[i]]=d[U]+1;
q.push(v[i]);
}
}
return d[T]!=-1;
}
db dfs(int U,db a)
{
if(U==T||a<=EPS)
return a;
db Flow=0.0,f;
for(int &i=cur[U];i!=-1;i=next[i])
if(d[v[i]]==d[U]+1&&(f=dfs(v[i],min(a,cap[i])))>EPS)
{
cap[i]-=f;
cap[i^1]+=f;
Flow+=f;
a-=f;
if(a<=EPS)
break;
}
if(Flow<=EPS) d[U]=-1;
return Flow;
}
db MaxFlow()
{
db Flow=0.0,tmp;
while(bfs())
{
memcpy(cur,first,sizeof(int)*(nn+1));
while((tmp=dfs(S,INF))>EPS) Flow+=tmp;
}
return Flow;
}
bool check(db Lim)
{
memset(first,-1,sizeof(int)*(nn+1));
en=0;
for(int i=1;i<=m;++i)
AddEdge(S,1+i,Lim*(db)b[i]);
for(int i=1;i<=n;++i)
AddEdge(1+m+i,T,(db)a[i]);
for(int i=1;i<=m;++i)
for(int j=1;j<=n;++j)
if(can[i][j])
AddEdge(1+i,1+m+j,INF);
return fabs(MaxFlow()-(db)sumv)<=EPS?1:0;
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;++i)
{
scanf("%d",&a[i]);
sumv+=a[i];
}
for(int i=1;i<=m;++i) scanf("%d",&b[i]);
for(int i=1;i<=m;++i)
for(int j=1;j<=n;++j)
scanf("%d",&can[i][j]);
S=1; T=nn=m+n+2;
db l=0.0,r=5000000.0;
while(r-l>EPS)
{
db mid=(l+r)/2.0;
if(check(mid))
r=mid-EPS;
else
l=mid+EPS;
}
printf("%lf\n",l);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: