1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127
| #include<algorithm> #include<iostream> #include<iomanip> #include<cstring> #include<cstdlib> #include<climits> #include<vector> #include<cstdio> #include<cmath> #include<queue> using namespace std;
typedef long long LL;
inline const int Get_Int() { int num=0,bj=1; char x=getchar(); while(x<'0'||x>'9') { if(x=='-')bj=-1; x=getchar(); } while(x>='0'&&x<='9') { num=num*10+x-'0'; x=getchar(); } return num*bj; } const int maxn=100005;
struct Edge { int from,to,cap,flow; LL cost; Edge(int x=0,int y=0,int c=0,int f=0,LL co=0):from(x),to(y),cap(c),flow(f),cost(co) {} };
int n,m,p[45],map[45][105],sum=0;
int id(int j,int k) { return n+(j-1)*sum+k; }
struct MinimumCost_MaximumFlow { int n,m,A,B; vector<Edge>edges; vector<int>G[maxn]; bool inque[maxn]; int a[maxn],path[maxn]; LL dist[maxn]; void init(int n) { this->n=n; edges.clear(); for(int i=1; i<=n; i++)G[i].clear(); } void AddEdge(int x,int y,int v,LL f) { edges.push_back(Edge(x,y,v,0,f)); edges.push_back(Edge(y,x,0,0,-f)); m=edges.size(); G[x].push_back(m-2); G[y].push_back(m-1); } bool bellmanford(int n,int s,int t,int& flow,LL& cost) { for(int i=1; i<=this->n; i++)dist[i]=LLONG_MAX/2; memset(inque,0,sizeof(inque)); queue<int>Q; Q.push(s); dist[s]=path[s]=0; a[s]=INT_MAX; while(!Q.empty()) { int Now=Q.front(); Q.pop(); inque[Now]=0; for(int id:G[Now]) { Edge& e=edges[id]; int Next=e.to; if(e.cap>e.flow&&dist[Next]>dist[Now]+e.cost) { dist[Next]=dist[Now]+e.cost; path[Next]=id; a[Next]=min(a[Now],e.cap-e.flow); if(!inque[Next]) { Q.push(Next); inque[Next]=1; } } } } if(dist[t]==LLONG_MAX/2)return false; flow+=a[t]; cost+=dist[t]*a[t]; for(int Now=t; Now!=s; Now=edges[path[Now]].from) { if(edges[path[Now]].to==t) { int tmp=edges[path[Now]].from; B=(tmp-n)%sum+1; A=(tmp-n-B+1)/sum+1; } edges[path[Now]].flow+=a[t]; edges[path[Now]^1].flow-=a[t]; } return true; } int maxflow(int n,int s,int t,LL& cost) { int flow=0; cost=0; while(bellmanford(n,s,t,flow,cost)) for(int i=1; i<=n; i++)AddEdge(i,id(A,B),1,B*map[i][A]); return flow; } } mcmf;
int main() { n=Get_Int(); m=Get_Int(); for(int i=1; i<=n; i++)p[i]=Get_Int(),sum+=p[i]; int S=m*sum+n+1,T=m*sum+n+2; mcmf.init(T); for(int i=1; i<=n; i++)mcmf.AddEdge(S,i,p[i],0); for(int i=1; i<=m*sum; i++)mcmf.AddEdge(n+i,T,1,0); for(int i=1; i<=n; i++) for(int j=1; j<=m; j++) map[i][j]=Get_Int(); for(int i=1; i<=n; i++) for(int j=1; j<=m; j++) mcmf.AddEdge(i,id(j,1),1,map[i][j]); LL cost=0; mcmf.maxflow(n,S,T,cost); printf("%lld\n",cost); return 0; }
|