把矩阵中的每一个当成一个一个点表示第j位研究院倒数第p个完成修车,所以link<i,get(j,p)>,添加超级源和超级汇,费用流
/************************************************************** Problem: 1070 User: BPM136 Language: C++ Result: Accepted Time:656 ms Memory:95496 kb ****************************************************************/ #include<iostream> #include<cstdio> #include<cmath> #include<cstring> #include<cstdlib> #include<algorithm> #include<bitset> #define LL long long #define fo(i,a,b) for(int i=a;i<=b;i++) #define efo(i,x) for(int i=last[x];i!=0;i=e[i].next) using namespace std; #define N 300 #define M 100 #define inf 1000000007 #define S n*m+n+1 #define T n*m+n+2 struct edge { int y,f,c,next; }e[N*M*M]; int last[N*M*N],ne=1; int a[M][N]; int n,m,ans=0; int get(int x,int y) { return x*n+y; } void add(int x,int y,int f,int c) { e[++ne].y=y;e[ne].c=c;e[ne].f=f;e[ne].next=last[x];last[x]=ne; } void add2(int x,int y,int f,int c) { // cout<<x<<' '<<y<<' '<<f<<' '<<c<<endl; add(x,y,f,c);add(y,x,0,-c); } int dis[N*M+M],pre[N*M+M],lo[N*M+M]; int q[N*M*M]; bitset<N*M+M>inq; bool spfa(int s,int tt) { inq.reset(); memset(lo,0,sizeof(lo)); memset(pre,0,sizeof(pre)); fo(i,0,N*M+M-1)dis[i]=inf; dis[s]=0;inq[s]=1;q[1]=s; int h=0,t=1; while(h<t) { int now=q[++h]; efo(i,now) if(e[i].f&&dis[now]+e[i].c<dis[e[i].y]) { dis[e[i].y]=dis[now]+e[i].c; lo[e[i].y]=i; pre[e[i].y]=now; if(inq[e[i].y]==0) { q[++t]=e[i].y; inq[e[i].y]=1; } } inq[now]=0; } if(dis[tt]==inf)return 0; else return 1; } void mcf(int s,int tt) { while(spfa(s,tt)) { // cout<<s<<' '<<tt<<endl; int x=tt,mi=inf; while(pre[x]!=0) { mi=min(mi,e[lo[x]].f); x=pre[x]; } x=tt; while(pre[x]!=0) { ans+=mi*e[lo[x]].c; e[lo[x]].f-=mi; e[lo[x]^1].f+=mi; x=pre[x]; } } } int main() { scanf("%d%d",&m,&n); fo(i,1,n) fo(j,1,m) scanf("%d",&a[i][j]); fo(i,1,n) { fo(j,1,m) fo(p,1,n) { add2(i,get(j,p),1,p*a[i][j]); } add2(S,i,1,0); } fo(i,1,m) fo(j,1,n) add2(get(i,j),T,1,0); mcf(S,T); double anss=(double)(1.0*ans)/(1.0*n); printf("%.2lf\n",anss); return 0; }