这标题只是用来吸引您的注意的(笑。
这费用流打一次错一次,T了 5 个点,疑似死循环。
#include<bits/stdc++.h>
#define inf 0x3f3f3f3f
using namespace std;
int n,m,tot=1,vis[5200010],dis[5200010],cot[520][520];
int top[5200010],pre[5200010];
int head[5200010],ans,s,t;
struct edge{
int to,nxt,val,spend;
}e[5200010];
inline void add(int u,int v,int val,int spend){
e[++tot].to=v;
e[tot].nxt=head[u];
e[tot].val=val;
e[tot].spend=spend;
head[u]=tot;
e[++tot].to=u;
e[tot].nxt=head[v];
e[tot].val=0;
e[tot].spend=-spend;
head[v]=tot;
}
bool spfa(){
memset(dis,0x3f,sizeof dis);
queue<int>q;
q.push(s);
dis[s]=0;
vis[s]=1;
while(!q.empty()){
int x=q.front();q.pop();vis[x]=0;
for(int i=head[x];i;i=e[i].nxt){
int v=e[i].to;
if(e[i].val&&dis[v]>dis[x]+e[i].spend){
dis[v]=dis[x]+e[i].spend;
if(!vis[v]){
vis[v]=1;
q.push(v);
}
}
}
}
return (dis[t]!=inf);
}
int dfs(int x,int sum){
if(x==t)return sum;
int res=0;vis[x]=1;
for(int i=head[x];i&∑i=e[i].nxt){
int v=e[i].to;
if(e[i].val&&!vis[v]&&dis[v]==dis[x]+e[i].spend){
int k=dfs(v,min(sum,e[i].val));
e[i].val-=k;
e[i^1].val+=k;
sum-=k;
res+=k;
ans+=k*e[i].spend;
pre[x]=v;
}
}
if(!res)dis[x]=inf;
vis[x]=0;
return res;
}
void dinic(){
while(spfa()){
dfs(s,inf);
for(int i=1;i<=m;i++){
if(pre[n+((i-1)*n+top[i])]&&top[i]<n){
top[i]++;
int now=n+(i-1)*n+top[i];
for(int j=1;j<=n;j++){
add(j,now,1,cot[j][i]*top[i]);
}
add(now,t,1,0);
}
}
}
}
signed main(){
cin>>m>>n;
s=m*n+n+1;t=s+1;
for(int i=1;i<=n;i++){
add(s,i,1,0);
}
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
cin>>cot[i][j];
add(i,n+(j-1)*n+1,1,cot[i][j]);
}
}
for(int i=1;i<=m;i++){
top[i]=1;
add(n+(i-1)*n+1,t,1,0);
}
dinic();
printf("%.2f",(double)ans/(double)n);
}