1070: [SCOI2007]修车

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;
}




你可能感兴趣的:(1070: [SCOI2007]修车)