建图看hzwer的blog吧QAQ讲得超好
第一次写zkw费用流……为了学这个专门去看了KM…………
WA了一年……
zkw倒是一遍写对了
然而
n,m写反,调了一年
……真的……不想承认……我费用流建边写错了……反向边……的费用……我……写的是……零………………
mdzz,看来要退役了
#include<bits/stdc++.h>
#define INF 0x3f3f3f3f
#define MAXN 700
#define MAXM 70000
using namespace std; int n,m;
long long cost=0;
int S=0,T=657;
struct t1{
int to,nxt,c,liu;
t1(){}
t1(int to,int nxt,int c,int liu):to(to),nxt(nxt),c(c),liu(liu){}
}edge[MAXM]; int cnt_edge=1;
int fst[MAXN],cnt_node=0;
void addedge(int x,int y,int c,int liu){
edge[++cnt_edge]=t1(y,fst[x],c,liu);
fst[x]=cnt_edge;
edge[++cnt_edge]=t1(x,fst[y],-c,0);
fst[y]=cnt_edge;
}
int vis[MAXN],ust=0;
int flow(int now,int low){
if(now==T) return cost+=ust*low,low;
vis[now]=1;
int rst=low;
for(int tmp=fst[now];tmp;tmp=edge[tmp].nxt){
if((!edge[tmp].liu)||vis[edge[tmp].to]||edge[tmp].c) continue;
int aim=edge[tmp].to;
int dd=flow(aim,min(rst,edge[tmp].liu));
edge[tmp].liu-=dd,edge[tmp^1].liu+=dd,rst-=dd;
if(!rst) return low;
}
return low-rst;
}
bool check(){
int d=INF;
for(int i=S;i<=T;++i)
if(vis[i])
for(int tmp=fst[i];tmp;tmp=edge[tmp].nxt)
if(edge[tmp].liu&&(!vis[edge[tmp].to])&&edge[tmp].c<d)
d=edge[tmp].c;
if(d==INF) return 0;
for(int i=S;i<=T;++i)
if(vis[i])
for(int tmp=fst[i];tmp;tmp=edge[tmp].nxt)
edge[tmp].c-=d,edge[tmp^1].c+=d;
return ust+=d,1;
}
void cost_flow(){
do
do{
// puts("QAQ");
memset(vis,0,sizeof vis);
} while(flow(S,INF));
while(check());
}
int id_node[10][61];
int read_t;
int main(){
scanf("%d%d",&m,&n);
cnt_node=n;
for(int i=1;i<=n;++i) addedge(S,i,0,1);
for(int i=1;i<=m;++i)
for(int j=1;j<=n;++j)
id_node[i][j]=++cnt_node,
addedge(cnt_node,T,0,1);
for(int i=1;i<=n;++i)
for(int j=1;j<=m;++j){
scanf("%d",&read_t);
int ttmp=read_t*n;
for(int k=1;k<=n;++k,ttmp-=read_t)
addedge(i,id_node[j][k],ttmp,1);
}
cost_flow();
printf("%.2f",1.0*cost/n);
return 0;
}