/*
bzoj1070 费用流
Time:2017-10-25
Author:lcy

http://hzwer.com/2877.html

n个人同时要修车,m个工人可以修车,
给出每个工人修每辆车的时间,
求每个人最小等待时间

拆点,每个工人分成n个点,每个点表示一个槽,
第i个点表示这个工人要修的倒数第i辆车。

n辆车,每辆都和一个工人的点连边,容量为1,费用
计算很有意思,可以参照链接。

源点连向每辆车,容量1,费用0。每个工人点连向
汇点,容量1,费用0。

流量是变量,建图给流量不同的选择,费用流算法则保证
能达成最大流最小费用目标。这里面最大流即为所有的车都能在不同
的时间段被修,而费用最小即为等待时间总和最小。
*/
#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define fr(i,a,b) for(int i=a;i<=b;i++)
#define frr(i,a,b) for(int i=a;i>=b;i--)
#define ms(a,b) memset(a,b,sizeof(a))
#define scfd(a) scanf("%d",a)
#define scflf(a) scanf("%lf",a)
#define scfs(a) scanf("%s",a)
#define ptfd(a) printf("%d\n",a)
#define ptfs(a) printf("%s\n",a)
#define showd(a,b) printf(a"=%d\n",b)
#define showlf(a,b) printf(a"=%lf\n",b)
#define shows(a,b) printf(a"=%s\n",b)
#define mmcp(a,b) memcpy(a,b,sizeof(b))
#define pb(a) push_back(a)
const int MAXN=700;
const int INF=21474836;
int n,m;
int tme[65][65];
struct edge{
    int f,t,cp,fl,cs;//price
    edge(int aa,int bb,int cc,int dd,int ee){
        f=aa,t=bb,cp=cc,fl=dd,cs=ee;
    }
    edge(){

    }
};
edge e[100005];
vector<int>g[MAXN];
bool v[MAXN];
int a[MAXN],d[MAXN],fa[MAXN],ed;
int flow,cost;
void add_edge(int ff,int tt,int cc,int pp){
    //printf("build %d to %d,cap=%d,flow=%d,cost=%d\n",ff,tt,cc,0,pp);
    e[ed++]=edge(ff,tt,cc,0,pp);
    e[ed++]=edge(tt,ff,0,0,-1*pp);
    g[ff].push_back(ed-2);
    g[tt].push_back(ed-1);
}
bool bmf(int start,int end){
    ms(v,false);
    fr(i,1,end)d[i]=INF;d[start]=0;
    ms(a,0);
    queue<int>q;
    q.push(start);v[start]=true;a[start]=INF;d[start]=0;
    while(!q.empty()){
        int t=q.front();q.pop();v[t]=false;
        int sz=g[t].size();
        fr(i,0,sz-1){
            edge ne=e[g[t][i]];
            if(ne.fl<ne.cp&&d[ne.t]>d[ne.f]+ne.cs){
                d[ne.t]=d[ne.f]+ne.cs;
                a[ne.t]=min(a[ne.f],ne.cp-ne.fl);
                fa[ne.t]=g[t][i];
                // printf("now=%d,fa=%d,fa_point=%d\n",ne.t,fa[ne.t],ne.f);
                if(!v[ne.t]){q.push(ne.t);v[ne.t]=true;}
            }
        }
    }
    if(!a[end])return false;
    for(int i=end;i!=start;i=e[fa[i]].f){
        e[fa[i]].fl+=a[end];
        e[fa[i]^1].fl-=a[end];
    }
    flow+=a[end];
    cost+=d[end]*a[end];
    return true;
}
void min_cost(int start,int end){
    flow=cost=0;
    while(bmf(start,end));
}
int mm,nn,start,end;
int main(){
    scanf("%d%d",&mm,&nn);
	fr(i,1,nn)
		fr(j,1,mm)
            scanf("%d",&tme[i][j]);
    start=0,end=(mm+1)*nn+1;
	fr(i,1,mm)
		fr(j,1,nn){
			fr(k,1,nn)
                add_edge(k,i*nn+j,1,(nn-j+1)*tme[k][i]);
            add_edge(i*nn+j,end,1,0);
        }
            
	fr(i,1,nn)
        add_edge(0,i,1,0);  
    min_cost(start,end);
    printf("%.2lf\n",(double)cost/(double)nn);
    return  0;
}
 posted on 2017-10-25 12:20  cylcy  阅读(66)  评论(0编辑  收藏  举报