您的位置:首页 > 其它

[bzoj1070][SCOI2007]修车【费用流】

2018-03-06 19:16 387 查看
【题目链接】

  http://www.lydsy.com/JudgeOnline/problem.php?id=1070

【题解】

  建图方式还是挺神的。

  我们不考虑每辆车之前的等待花费,而是考虑每辆车对之后的车的影响,因此,我们把每辆车插到最前面。费用为它即它后面的车数×它的时间它即它后面的车数×它的时间。

  因此,把每个技术人员拆成nn个点,每个点的流量限制为11,表示倒数第ii个修的车。

  每辆车也建一个点,向每个计数人员的每个时间连边。费用为i∗costi∗cost

/* --------------
user Vanisher
problem
----------------*/
# include <bits/stdc++.h>
# define    ll      long long
# define    inf     0x3f3f3f3f
# define    M       100010
# define    N       1010
# define    MM      20
# define    NN      100
using namespace std;
int read(){
int tmp=0, fh=1; char ch=getchar();
while (ch<'0'||ch>'9'){if (ch=='-') fh=-1; ch=getchar();}
while (ch>='0'&&ch<='9'){tmp=tmp*10+ch-'0'; ch=getchar();}
return tmp*fh;
}
struct node{
int data,next,l,vote,re;
}e[M];
int place,head
,dis
,use
,can
,ned
,frm
,n,m,S,T,q
,ti;
int mp[MM][NN],pin[MM][NN],p[NN];
ll ans;
void build(int u, int v, int l, int w){
e[++place].data=v; e[place].next=head[u]; head[u]=place; e[place].vote=w; e[place].l=l; e[place].re=place+1;
e[++place].data=u; e[place].next=head[v]; head[v]=place; e[place].vote=-w; e[place].l=0; e[place].re=place-1;
}
void spfa(){
memset(dis,inf,sizeof(dis));
memset(use,0,sizeof(use));
dis[S]=0; use[S]=1; can[S]=inf;
int pl=1, pr=1; q[1]=S;
while (pl<=pr){
int x=q[(pl++)%N];
for (int ed=head[x]; ed!=0; ed=e[ed].next)
if (dis[e[ed].data]>dis[x]+e[ed].vote&&e[ed].l!=0){
dis[e[ed].data]=dis[x]+e[ed].vote;
can[e[ed].data]=min(e[ed].l,can[x]);
frm[e[ed].data]=ed;
if (use[e[ed].data]==0){
use[e[ed].data]=1;
q[(++pr)%N]=e[ed].data;
}
}
use[x]=0;
}
}
void change(){
ans=ans+(long long)dis[T]*(long long)can[T];
int now=T;
while (now!=S){
e[frm[now]].l-=can[T];
e[e[frm[now]].re].l+=can[T];
now=e[e[frm[now]].re].data;
}
}
void flow(){
for (spfa(); dis[T]!=inf; spfa())
change();
}
int main(){
m=read(), n=read();
S=0; T=1; ti=1;
for (int i=1; i<=n; i++)
for (int j=1; j<=m; j++){
mp[j][i]=read();
pin[j][i]=++ti;
build(pin[j][i],T,1,0);
}
for (int i=1; i<=n; i++){
p[i]=++ti;
build(S,p[i],1,0);
for (int j=1; j<=m; j++)
for (int k=1; k<=n; k++)
build(p[i],pin[j][k],1,mp[j][i]*k);
}
flow();
printf("%.2lf\n",ans*1.0/n);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: