【网络流】【费用流】[SCOI2007]修车
同一时刻有N位车主带着他们的爱车来到了汽车维修中心。维修中心共有M位技术人员,不同的技术人员对不同的车进行维修所用的时间是不同的。现在需要安排这M位技术人员所维修的车及顺序,使得顾客平均等待的时间最小。 说明:顾客的等待时间是指从他把车送至维修中心到维修完毕所用的时间。
输入:
2 2 3 2 1 4输出:
1.50
数据范围: (2<=M<=9,1<=N<=60),
(1<=T<=1000)
首先可以发现如果直接进行暴力的话那么枚举每个人的复杂度是O(M*2^N)该复杂度令人难以接受,
每个人只可以被使用一次。。。可以通过网络流来限制流量,然后如果每个人跑一次网络流。。。根本不能友好的玩耍。
但是如果每个人最多处理N辆车,那么可以处理对于每一个人来说第K辆车是当前这个人的倒数第i个处理的那么就相当于这个人第N-i+1个节点,因为是倒数第i个后面还有i-1个车等待当前工作人员处理,那么浪费的时间就是(i-1)*T+T 加一个T的原因是当前处理现在这辆车也要耗费时间
代码如下:
#include <cstdio> #include <cstring> #include <algorithm> #include <iostream> #include <queue> using namespace std; const int MAXN = 2000; const int INF = 1e9+7; const int MAXM = 100000; struct node{ int v, cost, cap; node *next, *back; }Edges[MAXM*2+10], *ecnt=Edges, *adj[MAXN+10]; int dis[MAXN+10], res[MAXN+10]; node *Fa[MAXN+10]; void addedge(int u, int v, int ca, int co){ ++ecnt; ecnt->v = v; ecnt->cap = ca; ecnt->cost = co; ecnt->next = adj[u]; ecnt->back = ecnt+1; adj[u] = ecnt; ++ecnt; ecnt->v = u; ecnt->cap = 0; ecnt->cost = -co; ecnt->next = adj[v]; ecnt->back = ecnt-1; adj[v] = ecnt; } int ncnt, s, t; bool SPFA(){ for(int i=1;i<=ncnt;i++) dis[i]=INF; dis[s] = 0; queue<int> que; que.push(s); res[s] = INF; while(!que.empty()){ int u = que.front(); que.pop(); for(node *p=adj[u];p;p=p->next){ if(p->cap == 0) continue; if(dis[p->v] <= dis[u] + p->cost) continue; dis[p->v] = dis[u] + p->cost; Fa[p->v] = p; res[p->v] = min(res[u], p->cap); que.push(p->v); } } return !(dis[t] == INF); } int work(){ int ret = 0; while(SPFA()){ ret += res[t] * dis[t]; int now = t; while(now != s){ Fa[now]->cap -= res[t]; Fa[now]->back->cap += res[t]; now = Fa[now]->back->v; } } return ret; } int n, m; int main(){ while(~scanf("%d%d", &m, &n)){ memset(adj, 0, sizeof adj); ecnt=Edges; s=1, t=m*n+n+2;ncnt = m*n+n+2; int tmp; for(int i=1;i<=n;i++){ addedge(1, i+1, 1, 0); for(int j=1;j<=m;j++){ scanf("%d", &tmp); for(int k=1;k<=n;k++) addedge(i+1, 1+n*j+k, 1, (n-k)*tmp+tmp); } } for(int i=1;i<=m;i++) for(int j=1;j<=n;j++) addedge(1+n*i+j, t, 1, 0); printf("%.2lf\n", work()*1.0/n); } return 0; }