[bzoj 1070][SCOI 2007]修理車【料金フロー】


【タイトルリンク】http://www.lydsy.com/JudgeOnline/problem.php?id=1070 【問題解】建図の仕方はやはり神々しい.私たちは車ごとに前の待ち時間を考えず、車ごとに後の車に与える影響を考えています.そのため、車ごとに一番前に挿入します.料金はその後ろの車数です×その時間は後ろの車の数です× その時間.従って、各技術者をn n点に分解し、各点の流量を1に制限し、最後からi番目に修理された車を示す.各車にもポイントが建てられ、計数員一人一人の時間につながっています.費用はi∗cost i∗c o s t
/* --------------
    user Vanisher
    problem
----------------*/
# include 
# define    ll      long long
# define    inf     0x3f3f3f3f
# define    M       100010
# define    N       1010
# define    MM      20
# define    NN      100
using namespace std;
int read(){
    int tmp=0, fh=1; char ch=getchar();
    while (ch<'0'||ch>'9'){if (ch=='-') fh=-1; ch=getchar();}
    while (ch>='0'&&ch<='9'){tmp=tmp*10+ch-'0'; ch=getchar();}
    return tmp*fh;
}
struct node{
    int data,next,l,vote,re;
}e[M];
int place,head[N],dis[N],use[N],can[N],ned[N],frm[N],n,m,S,T,q[N],ti;
int mp[MM][NN],pin[MM][NN],p[NN];
ll ans;
void build(int u, int v, int l, int w){
    e[++place].data=v; e[place].next=head[u]; head[u]=place; e[place].vote=w; e[place].l=l; e[place].re=place+1;
    e[++place].data=u; e[place].next=head[v]; head[v]=place; e[place].vote=-w; e[place].l=0; e[place].re=place-1;
}
void spfa(){
    memset(dis,inf,sizeof(dis));
    memset(use,0,sizeof(use));
    dis[S]=0; use[S]=1; can[S]=inf;
    int pl=1, pr=1; q[1]=S;
    while (pl<=pr){
        int x=q[(pl++)%N];
        for (int ed=head[x]; ed!=0; ed=e[ed].next)
            if (dis[e[ed].data]>dis[x]+e[ed].vote&&e[ed].l!=0){
                dis[e[ed].data]=dis[x]+e[ed].vote;
                can[e[ed].data]=min(e[ed].l,can[x]);
                frm[e[ed].data]=ed;
                if (use[e[ed].data]==0){
                    use[e[ed].data]=1;
                    q[(++pr)%N]=e[ed].data;
                }
            }
        use[x]=0;
    }
}
void change(){
    ans=ans+(long long)dis[T]*(long long)can[T];
    int now=T;
    while (now!=S){
        e[frm[now]].l-=can[T];
        e[e[frm[now]].re].l+=can[T];
        now=e[e[frm[now]].re].data;
    }
}
void flow(){
    for (spfa(); dis[T]!=inf; spfa())
        change();
}
int main(){
    m=read(), n=read();
    S=0; T=1; ti=1;
    for (int i=1; i<=n; i++)
        for (int j=1; j<=m; j++){
            mp[j][i]=read();
            pin[j][i]=++ti;
            build(pin[j][i],T,1,0);
        }
    for (int i=1; i<=n; i++){
        p[i]=++ti;
        build(S,p[i],1,0);
        for (int j=1; j<=m; j++)
            for (int k=1; k<=n; k++)
                build(p[i],pin[j][k],1,mp[j][i]*k);
    }
    flow();
    printf("%.2lf
"
,ans*1.0/n); return 0; }