【bzoj】 1070: [SCOI2007]修车

 

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)

 

一个拆了很多很多点的网络流模型。(想法其实是先考虑一个修理师的情况,再考虑多个的情况)

把每个修理师拆成n个点,一辆车分别想着n个点连边,容量为1,费用为t * x  其中x = 1, 2, 3 ... n,表示在这之后修理车的人要总共等待t, t * 2, t * 3, t * 4...时间

然后跑一边最小费用最大流就可以了。

 

  1 #include<queue>
  2 #include<cstdio>
  3 #include<iostream>
  4 #define MAXN 100010
  5 
  6 using namespace std;
  7 
  8 const int INF=0x7fffffff;
  9 
 10 int a[1010][1010],fee[MAXN],pre[MAXN];
 11 
 12 int n,m,src,decc,ans;
 13 
 14 struct node {
 15     int to;
 16     int cost;
 17     int next;
 18     int val;
 19 };
 20 node e[MAXN*2];
 21 
 22 int head[MAXN],tot=1;
 23 
 24 bool vis[MAXN];
 25 
 26 queue<int> q;
 27 
 28 inline void read(int&x) {
 29     int f=1;x=0;char c=getchar();
 30     while(c>'9'||c<'0') {if(c=='-') f=-1;c=getchar();}
 31     while(c>='0'&&c<='9') {x=(x<<1)+(x<<3)+c-48;c=getchar();}
 32     x=x*f;
 33 }
 34 
 35 inline void add(int x,int y,int val,int cost) {
 36     e[++tot].to=y;
 37     e[tot].val=val;
 38     e[tot].cost=cost;
 39     e[tot].next=head[x];
 40     head[x]=tot;
 41 }
 42 
 43 inline void add_edge(int x,int y,int val,int cost) {
 44     add(x,y,val,cost);
 45     add(y,x,0,-cost);
 46 }
 47 
 48 inline int min_flow() {
 49     int flow=INF;
 50     for(int i=pre[decc];i;i=pre[e[i^1].to])
 51       flow=min(flow,e[i].val);
 52     for(int i=pre[decc];i;i=pre[e[i^1].to])
 53       e[i].val-=flow,e[i^1].val+=flow;
 54     return flow;
 55 }
 56 
 57 inline bool spfa() {
 58     for(int i=1;i<=decc;i++) fee[i]=INF;
 59     fee[src]=0;
 60     vis[src]=true;
 61     while(!q.empty()) q.pop(); 
 62     q.push(src);
 63     while(!q.empty()) {
 64         int u=q.front();
 65         q.pop();
 66         vis[u]=false;
 67         for(int i=head[u];i;i=e[i].next) {
 68             int to=e[i].to;
 69             if(fee[u]+e[i].cost<fee[to]&&e[i].val) {
 70                 fee[to]=fee[u]+e[i].cost;
 71                 pre[to]=i;
 72                 if(!vis[to]) {
 73                     q.push(to);
 74                     vis[to]=true;
 75                 }
 76             }
 77         }
 78     }
 79     return fee[decc]!=INF;
 80 }
 81 
 82 inline void build_graph() {
 83     for(int i=1;i<=n;i++)
 84       for(int j=1;j<=m;j++)
 85         for(int k=1;k<=n;k++)
 86           add_edge(i,j*n+k,1,a[i][j]*k);
 87     src=n*m+n+1;decc=n*m+n+2;
 88     for(int i=1;i<=n;i++)
 89       add_edge(src,i,1,0);
 90     for(int i=n+1;i<=n*m+n;i++)
 91       add_edge(i,decc,1,0);
 92 }
 93 
 94 int main() {
 95     read(m);read(n);
 96     for(int i=1;i<=n;i++)
 97       for(int j=1;j<=m;j++) 
 98         read(a[i][j]);
 99     build_graph();
100     while(spfa()) ans+=min_flow()*fee[decc];
101     printf("%.2lf\n",(double)ans/n);
102     return 0;
103 } 
代码

 

 

 

posted @ 2017-07-17 18:26  拿叉插猹哈  阅读(117)  评论(0编辑  收藏  举报