您的位置:首页 > 其它

bzoj1070————2016——3——14

2016-03-14 19:51 423 查看
传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=1070;

题目概括:

Description

同一时刻有N位车主带着他们的爱车来到了汽车维修中心。维修中心共有M位技术人员,不同的技术人员对不同的车进行维修所用的时间是不同的。现在需要安排这M位技术人员所维修的车及顺序,使得顾客平均等待的时间最小。 说明:顾客的等待时间是指从他把车送至维修中心到维修完毕所用的时间。

Input

第一行有两个m,n,表示技术人员数与顾客数。 接下来n行,每行m个整数。第i+1行第j个数表示第j位技术人员维修第i辆车需要用的时间T。

Output

最小平均等待时间,答案精确到小数点后2位。

Sample Input

2 2

3 2

1 4

Sample Output

1.50

HINT

数据范围: (2<=M<=9,1<=N<=60), (1<=T<=1000)

Source

看到这个大概就应该知道是费用流了吧,可是怎么处理一个人等其他人的时间呢? 显然拆点撒,拆T组点,每个人向第j的机器的第z个修的点连一条边,权植为z*time[i][j](为什么是这个呢?

因为你在修的时候别人和你都在等待),所以这道题就这样写完了,但感觉点有点多,所以就写了个(zkw费用流)但是是抄模板的。。。。。醉(好歹有点理解也是好的);

普通费用流也可以过,只不过要小心点.........

#include<iostream>
#include<cstring>
#include<cstdio>
#define inf 0x7fffffff
#define maxn 500000
int n,m,tot,s,t,ans;
int pre[maxn],v[maxn],cap[maxn],dis[maxn],sla[maxn],now[maxn],cost[maxn];
int a[100][100];
bool vis[maxn];
using namespace std;
int num(int i,int j)
{
return (i*n+j);
}
void ins(int a,int b, int c, int d)
{
tot++; pre[tot]=now[a]; now[a]=tot; v[tot]=b; cap[tot]=c; cost[tot]=d;
}
void insert(int a, int b, int c, int d)
{
ins(a,b,c,d); ins (b,a,0,-d);
}
int kk(int x, int f)
{
int left=f;
if (x==t) {ans+=f*dis[s]; return f;
}
vis[x]=1;
for (int i=now[x]; i; i=pre[i])
{
if (cap[i]>0 && !vis[v[i]])
{
if (dis[v[i]]+cost[i]-dis[x]==0)
{
int delt=kk(v[i],min(cap[i],left));
if (delt>0) cap[i]-=delt,cap[i^1]+=delt,left-=delt;
if (left==0) return f;

}
else
sla[v[i]]=min(sla[v[i]],dis[v[i]]+cost[i]-dis[x]);
}
}
return (f-left);
}
bool dfs()
{
int delt=inf;
for (int i=s; i<=t; i++)
if (!vis[i]) delt=min(delt,sla[i]),sla[i]=inf;
if (delt==inf ) return  true;
for (int i=s; i<=t; i++)
if (vis[i]) dis[i]+=delt;
return false;
}
void zkw()
{
for (int i=s; i<=t; i++) dis[i]=0,sla[i]=inf;
do{
do {memset(vis,0,sizeof(vis));
} while(kk(s,inf));

}while (!dfs());
}
int main()
{
scanf("%d%d",&m,&n);
for (int i=1; i <=n; i++) for (int j=1; j<=m; j++) scanf("%d",&a[i][j]);
tot=1;
s=0; t=n*m+n+1;
for (int i=1; i<=n; i++) insert(s,i,1,0);
for (int i=1; i<=n; i++)
for (int j=1; j<=m; j++)
for (int z=1; z<=n; z++)
{
insert(i,num(j,z),1,z*a[i][j]);
}
for (int i=1; i<=m; i++)
for (int j=1; j<=n; j++)
insert(num(i,j),t,1,0);
zkw();
printf("%.2lf\n",(1.0*ans)/(1.0*n));
}


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