hdu 5619 Jam's store(最小费用最大流)

Jam's store



Problem Description
Jam didn't study well,then he go to repair the computer in a store,there are  M staffs and  N guests, given each guests have to spend  Tij time to repair the computer by the  j staffs.

Now ask the total of time the guest at least to wait.
The staff wiil do the next work after he has done the current work
 

Input
The first line is  T(1T100) means  T Case

For each case

The first line is  M and  N(1M,N20) means the number of staffs and guests

Now given a Matrix with  NM each number means the  i guests to the  j staff time  (1Tij1000)
 

Output
Output one line about the time at least they need to wait
 

Sample Input
   
   
   
   
1 4 3 4 4 1 5 8 2 5 6 4 5 10 5
 

Sample Output
   
   
   
   
7
Hint
the first guest choose the third staff the second guest choose the second staff the third gurst choose the third staff the total of time is 4+2+1=7
 

Source
BestCoder Round #70
 

Recommend
hujie   |   We have carefully selected several similar problems for you:   5634  5633  5632  5629  5628 

建立一个源点与汇点还有一个汇点
源点到i顾客连接一条f=1,cost=0的边 限制顾客数
建立一张i顾客作为j店员的倒数第k个受理者的图
i顾客到所有店员(m)的所有可能的受理者位置(n)总共n*m个点建一条f=1,cost=a[i][j]*k的边
所有店员(m)的所有可能的受理者位置(n)到相对应的店员连接一条f=1,cost=0的边
所有店员到汇点连一条f=n,cost=0的边
然后运行最小费用最大流算法,这里用的是EK增强版
#include<cstdio>
#include<cstring>
#include<queue>
#include<cmath>
using namespace std;
#define M 5500
#define inf 0x3f3f3f3f
int cnt;
int head[M],pre[M],preedge[M],vis[M],dist[M];
struct node
{
    int u,v,f,cost,next;
}edge[M*M];
void add(int u,int v,int f,int cost)
{

    edge[cnt].u=u;
    edge[cnt].v=v;
    edge[cnt].f=f;
    edge[cnt].cost=cost;
    edge[cnt].next=head[u];
    head[u]=cnt++;
    edge[cnt].u=v;
    edge[cnt].v=u;
    edge[cnt].f=0;
    edge[cnt].cost=-cost;
    edge[cnt].next=head[v];
    head[v]=cnt++;
};
int spfa(int s,int t)
{
    int i,v,u;
    for(i=0;i<=t;i++)
    {
        vis[i]=0;
        dist[i]=inf;
    }
    queue<int>q;
    q.push(s);
    dist[s]=0;
    vis[s]=1;
    while(!q.empty())
    {
        u=q.front();
        q.pop();
        vis[u]=0;
        for(i=head[u];i!=-1;i=edge[i].next)
        {
            v=edge[i].v;
            if(edge[i].f&&dist[v]>dist[u]+edge[i].cost)
            {
                dist[v]=dist[u]+edge[i].cost;
                pre[v]=u;
                preedge[v]=i;
                if(!vis[v])
                {
                    vis[v]=1;
                    q.push(v);
                }
            }
        }
    }
    return dist[t]<inf;
}
int mincost(int s,int t)
{
    int flow,res,i,tmp;
    flow=0;
    res=0;
    while(spfa(s,t))
    {
        tmp=inf;
        for(i=t;i!=s;i=pre[i])
                tmp=min(tmp,edge[preedge[i]].f);
        for(i=t;i!=s;i=pre[i])
        {
            edge[preedge[i]].f-=tmp;
            edge[preedge[i]^1].f+=tmp;
        }
        flow+=tmp;
        res+=tmp*dist[t];
    }
    return res;
}
int main()
{
    int n,m,T,s,t,a[25][25],num;
    scanf("%d",&T);
    while(T--)
    {
        memset(head,-1,sizeof(head));
        cnt=0;
        scanf("%d%d",&m,&n);
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=m;j++)
            {
                scanf("%d",&a[i][j]);
            }
        }
        s=0;t=n+m*n+1;
        for(int i=1;i<=n;i++)
            add(s,i,1,0);
        num=n;
        for(int j=1;j<=m;j++)
        {
            for(int k=1;k<=n;k++)
            {
                ++num;
                for(int i=1;i<=n;i++)
                {
                    add(i,num,1,a[i][j]*k);
                }
                add(num,t,1,0);
            }
        }
        add(t,t+1,n,0);
        t++;
        printf("%d\n",mincost(s,t));
    }
    return 0;
}

你可能感兴趣的:(hdu 5619 Jam's store(最小费用最大流))