BZOJ 1070: [SCOI2007] repair the minimum cost maximum flow

title

1070 BZOJ
LUOGU 2053
Title Description

The same time there are N car owners with their car came to a car repair center. M service center has technical staff, technical staff of various different car repair time used is different. Now we need to arrange this M bit of skill in the repair of cars and order so that the average customer wait time to a minimum.
Description: Customer wait time is the time the service is completed with from his car to a service center to.

Input and output format
input format:

The first line has two numbers M, N, and the number represents the number of customers in the art.
Next n lines of m integers. I + 1 th row and j represents the number of times j-th bit of the i-maintenance technicians need to use vehicle T.

Output formats:

The minimum average waiting time, accurate answers to two decimal places.

Input Output Sample
Input Sample # 1:

2 2
3 2
1 4

Output Sample # 1:

1.50

Explanation

(2<=M<=9,1<=N<=60), (1<=T<=1000)

analysis

After reading the title, much like we found a bipartite graph matching problem, so it can be used to write a stream network.

Found that time the title is equivalent to the cost, you can write the cost of flow.

I wanted to: 1. establish \ (super source S \) , even with all the car side, a capacity of 1 at a cost of 0,

  1. Establish \ (super Meeting Point t \) , even with all the master side, a capacity of 1 at a cost of 0,
  2. Then all of the car with all the sides in accordance with the master even the cost matrix.

This seems to be the (right)?

Ah, after the \ (Chdy \) discussed, he awoke me to observe the data range, there must be a person to repair a lot of cars, these cars customers need to be in front of people restrictions, that is to say, customers of each repair are subject to person in front of the respective limits, i.e. split into a required number of master \ (n * m \) a, to meet the needs of each moment.

So the above chart only need to build a third step in detail on the line, the effect is the same.

Specific look at the code comments.

code

/*
    Problem:LUOGU 2053
    Author:G-hsm
    Date: 2019.6.17 06:38
    State: Solved
    Memo:最小费用最大流
*/

#include<bits/stdc++.h>
using namespace std;
const int maxn=1010,maxm=1e5+10,inf=0x3f3f3f3f;

char buf[1<<15],*fs,*ft;
inline char getc() { return (ft==fs&&(ft=(fs=buf)+fread(buf,1,1<<15,stdin),ft==fs))?0:*fs++; }
template<typename T>inline void read(T &x)
{
    x=0;
    T f=1, ch=getchar();
    while (!isdigit(ch) && ch^'-') ch=getchar();
    if (ch=='-') f=-1, ch=getchar();
    while (isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48), ch=getchar();
    x*=f;
}

template<typename T>inline void write(T x)
{
    if (!x) { putchar('0'); return ; }
    if (x<0) putchar('-'), x=-x;
    T num=0, ch[20];
    while (x) ch[++num]=x%10+48, x/=10;
    while (num) putchar(ch[num--]);
}

int ver[maxm<<1],edge[maxm<<1],Next[maxm<<1],cost[maxm<<1],head[maxn],len=1;
inline void add(int x,int y,int z,int c)
{
    ver[++len]=y,edge[len]=z,cost[len]=c,Next[len]=head[x],head[x]=len;
    ver[++len]=x,edge[len]=0,cost[len]=-c,Next[len]=head[y],head[y]=len;
}

int s,t;
int dist[maxn],incf[maxn],pre[maxn];
bool vis[maxn];
inline bool spfa()
{
    memset(dist,0x3f,sizeof(dist));
    memset(vis,0,sizeof(vis));
    queue<int>q;q.push(s);
    dist[s]=0,vis[s]=1,incf[s]=1<<30;
    while (!q.empty())
    {
        int x=q.front();
        q.pop();
        vis[x]=0;
        for (int i=head[x]; i; i=Next[i])
        {
            if (!edge[i]) continue;
            int y=ver[i];
            if (dist[y]>dist[x]+cost[i])
            {
                dist[y]=dist[x]+cost[i];
                incf[y]=min(incf[x],edge[i]);
                pre[y]=i;
                if (!vis[y]) q.push(y),vis[y]=1;
            }
        }
    }
    if (dist[t]==inf) return false;
    else return true;
}

long long maxflow,ans;
inline void update()
{
    int x=t;
    while (x!=s)
    {
        int i=pre[x];
        edge[i]-=incf[t];
        edge[i^1]+=incf[t];
        x=ver[i^1];
    }
    maxflow+=incf[t];
    ans+=dist[t]*incf[t];
}

int main()
{
    int m,n;//1~n 为车数,n+1~n+n*m 为师傅数
    read(m);read(n);
    for (int i=1; i<=n; ++i)
        for (int j=1,c; j<=m; ++j)
        {
            read(c);
            for (int k=1; k<=n; ++k) add(i,j*n+k,1,c*k);//add(i,n+hash(j,k),1,c*k);
        }//将m位师傅拆成n*m个点,第(i-1)*n+j个点表示的是在修第j辆车的第i位师傅

    s=0,t=n+n*m+1;
    for (int i=1; i<=n; ++i) add(s,i,1,0);//将源点与车分别连起来
    for (int i=n+1; i<=n+n*m; ++i) add(i,t,1,0);//将师傅分别与汇点连起来
    while (spfa()) update();
    printf("%.2f\n",ans/(double)n);
    return 0;
}

Guess you like

Origin www.cnblogs.com/G-hsm/p/11329989.html