題意
n個顧客m個服務員,給出每個服務員給每個顧客服務需要的時間,求顧客最小的等待時間
建圖
網絡流真是玄學啊,就是不會建圖。。
- 源點向每個客戶連邊,控制流量爲n
- 服務員拆點,每個客戶向每個服務員連n條邊,表示是該服務員倒數第k個服務的對象,代價爲k*cost[i] [j]
- 拆點後的服務員向匯點連邊
因此每個服務員會先確定最後一個服務的對象
代碼
#include <bits/stdc++.h>
#define mem(a,b) memset(a,b,sizeof(a))
#define rep(i,a,b) for(int i=a;i<b;i++)
#define debug(a) printf("a =: %d\n",a);
#define sc(x) scanf("%d",&x)
const int INF=0x3f3f3f3f;
const int maxn=500+50;
const int Mod=1000000007;
const double PI=acos(-1);
typedef long long ll;
typedef unsigned int ui;
using namespace std;
struct Edge{
int from,to,cap,flow,cost;
Edge() {}
Edge(int from, int to, int cap, int flow, int cost) : from(from), to(to), cap(cap), flow(flow), cost(cost) {}
};
struct MCMF{
int m;
vector<Edge> edges;
vector<int> G[maxn];
int inq[maxn];
int d[maxn];
int p[maxn];
int a[maxn];
void init(int n){
for(int i=0;i<=n;i++) G[i].clear();
edges.clear();
}
void addEdge(int from,int to,int cap,int cost){
edges.push_back(Edge(from,to,cap,0,cost));
edges.push_back(Edge(to,from,0,0,-cost));
m=edges.size();
G[from].push_back(m-2);
G[to].push_back(m-1);
}
bool spfa(int s,int t,int &flow,int &cost){
mem(d,0x3f); mem(inq,0); mem(a,0);
d[s]=0; inq[s]=1; p[s]=0; a[s]=INF;
queue<int> qu;
qu.push(s);
while(!qu.empty()){
int u=qu.front(); qu.pop();
inq[u]=0;
int sz=G[u].size();
for(int i=0;i<sz;i++){
Edge &edge=edges[G[u][i]];
if(edge.cap>edge.flow && d[edge.to]>d[u]+edge.cost){
d[edge.to]=d[u]+edge.cost;
p[edge.to]=G[u][i];
a[edge.to]=min(a[u],edge.cap-edge.flow);
if(!inq[edge.to]){
qu.push(edge.to);
inq[edge.to]=1;
}
}
}
}
if(d[t]==INF) return false;
flow+=a[t];
cost+=d[t]*a[t];
int u=t;
while(u!=s){
edges[p[u]].flow+=a[t];
edges[p[u]^1].flow-=a[t];
u=edges[p[u]].from;
}
return true;
}
int minCost(int s,int t){
int flow=0,cost=0;
while(spfa(s,t,flow,cost));
//cout<<"flow "<<flow<<endl;
return cost;
}
};
int s[233][233];
MCMF mcmf;
int main()
{
#ifndef ONLINE_JUDGE
//freopen("/home/martin/ClionProjects/untitled/in.txt","r",stdin);
//freopen("/home/martin/ClionProjects/untitled/out.txt","w",stdout);
#endif
int T; scanf("%d",&T);
for(int cs=1;cs<=T;cs++){
int n,m;
scanf("%d %d",&m,&n);
//scanf("%d %d",&n,&m);
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
scanf("%d",&s[i][j]);
int N=1+n+n*m;
mcmf.init(N+1);
for(int i=1;i<=n;i++)
mcmf.addEdge(0,i,1,0);
for(int j=1;j<=m;j++)
for(int i=1;i<=n;i++){
for(int k=1;k<=n;k++){
mcmf.addEdge(i,j*n+k,1,k*s[i][j]);
}
}
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
mcmf.addEdge(j*n+i,N,1,0);
printf("%d\n",mcmf.minCost(0,N));
//printf("Case #%d: %d\n",cs,mcmf.minCost(0,N));
}
return 0;
}