您的位置:首页 > 其它

【bzoj 1070】修车(费用流)

2018-01-16 19:55 176 查看
传送门biu~

把每个工人拆成n个点,源点连每个n×m的点,流量为1,费用为0。n×m的点连每辆车,流量为1,费用为timei,j×k。每辆车连汇点,流量为1,费用为0。因为每个工人修车所带来的影响是它和它后面的车的等待时间都增加了timei,j。

#include<bits/stdc++.h>
using namespace std;
const int INF=1e9;
int n,m,S,T,cost,t[65][15];
int head[1005],nex[100005],to[100005],cap[100005],val[100005],tp=1;
int fir[1005],dis[1005];
bool b[1005];
inline void add(int x,int y,int c,int v){
nex[++tp]=head[x];
head[x]=tp;
to[tp]=y;
cap[tp]=c;
val[tp]=v;
}
inline void Insert(int x,int y,int c,int v){add(x,y,c,v);add(y,x,0,-v);}
inline bool spfa(){
queue<int>q;
for(int i=S;i<=T;++i)       dis[i]=INF,b[i]=false;
dis[S]=0;q.push(S);
while(!q.empty()){
int x=q.front();q.pop();b[x]=false;
for(int i=head[x];i;i=nex[i]){
if(cap[i] && dis[x]+val[i]<dis[to[i]]){
dis[to[i]]=dis[x]+val[i];
if(!b[to[i]]){
q.push(to[i]);
b[to[i]]=true;
}
}
}
}
return dis[T]^INF;
}
int dfs(int x,int now){
if(x==T || !now){
cost+=now*dis[T];
return now;
}
int c=0;
b[x]=true;
for(int &i=fir[x];i;i=nex[i]){
if(!b[to[i]] && cap[i] && dis[to[i]]==dis[x]+val[i]){
int f=dfs(to[i],min(now,cap[i]));
now-=f;
cap[i]-=f;
cap[i^1]+=f;
c+=f;
if(!now)    break;
}
}
return c;
}
inline int Dinic(){
int c=0;
while(spfa()){
for(int i=S;i<=T;++i)       fir[i]=head[i];
c+=dfs(S,INF);
}
return c;
}
int main(){
scanf("%d%d",&n,&m);S=0;T=n*m+m+1;
for(int i=1;i<=m;++i)
for(int j=1;j<=n;++j)
scanf("%d",&t[i][j]);
for(int i=1;i<=n*m;++i)         Insert(S,i,1,0);
for(int i=n*m;i<=n*m+m;++i)     Insert(i,T,1,0);
for(int i=1;i<=n;++i)
for(int j=1;j<=m;++j)
for(int k=1;k<=m;++k)
Insert((i-1)*m+j,n*m+k,1,t[k][i]*j);
Dinic();
printf("%.2lf",(double)cost/m);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: