您的位置:首页 > 其它

1070: [SCOI2007]修车

2016-02-14 19:15 295 查看

1070: [SCOI2007]修车

Time Limit: 1 Sec  Memory Limit: 162 MB
Submit: 3691  Solved: 1491

[Submit][Status][Discuss]

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



[Submit][Status][Discuss]


这题用网络流简直了。。。

将每个工人拆成n个点,分别代表第i个工人正在修倒数第j辆车将n辆车分别与这些点建边,费用为t[i][j]*k同时超级源超级汇等。。各边容量均为1,最后一遍最小费用最大流

为什么这样做呢?因为维修一辆车的时间只对其后面的维修造成影响,如果它是该工人修的倒数第k辆车,那么影响k次



#include<iostream>
#include<cstdio>
#include<queue>
#include<vector>
using namespace std;

const int maxn = 70;
typedef double DB;

vector <int> v[maxn*maxn*maxn];
queue <int> q;

struct E{
int from,to,cap,flow,w;
}G[1000000];

DB cost = 0;
int n,m,cnt = 0,t[maxn][maxn],dis[maxn*maxn*maxn],fa[maxn*maxn*maxn],a[maxn*maxn*maxn];
bool vis[maxn*maxn*maxn];

void Add(int from,int to,int c,int w)
{
v[from].push_back(cnt); G[cnt++] = (E){from,to,c,0,w};
v[to].push_back(cnt); G[cnt++] = (E){to,from,0,0,-w};
}

bool spfa()
{
for (int i = 1; i <= m+n*m+1; i++) dis[i] = ~0U>>1,vis[i] = 0;
dis[0] = 0; vis[0] = 1; a[0] = ~0U>>1;
q.push(0);
while (!q.empty()) {
int k = q.front(); q.pop(); vis[k] = 0;
for (int i = 0; i < v[k].size(); i++) {
E e = G[v[k][i]];
if (e.cap > e.flow && dis[e.to] > dis[k] + e.w) {
dis[e.to] = dis[k] + e.w;
a[e.to] = min(a[k],e.cap - e.flow);
fa[e.to] = v[k][i];
if (!vis[e.to]) {
vis[e.to] = 1; q.push(e.to);
}
}
}
}

if (dis[m+m*n+1] == ~0U>>1) return 0;
int A = a[m+m*n+1];
cost += (DB)(A)*(DB)(dis[m+m*n+1]);
int u = m+m*n+1;
while (u) {
G[fa[u]].flow += A;
G[fa[u]^1].flow -= A;
u = G[fa[u]].from;
}
return 1;
}

int main()
{
#ifdef YZY
freopen("yzy.txt","r",stdin);
#endif

cin >> n >> m;
for (int i = 1; i <= m; i++)
for (int j = 1; j <= n; j++)
scanf("%d",&t[j][i]);

for (int i = 1; i <= m; i++) Add(0,i,1,0);
for (int i = 1; i <= m; i++)
for (int j = m+1; j <= m+n*m; j++) {
int w = (j-m-1)/m + 1;
int k = (j-m)%m; if (!k) k = m;
Add(i,j,1,t[w][i]*k);
}
for (int i = m+1; i <= m+n*m; i++) Add(i,m+n*m+1,1,0);

while (spfa());
printf("%.2f",cost/(DB)(m));
return 0;
}


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