1. 程式人生 > >洛谷P3980 [NOI2008]誌願者招募

洛谷P3980 [NOI2008]誌願者招募

span bsp bool sum pair ret spa ace gpo

動態加邊網絡流

  1 #include<cstdio>
  2 #include<cstdlib>
  3 #include<algorithm>
  4 #include<cstring>
  5 #include<vector>
  6 #include<queue>
  7 #define rint register int
  8 #define ll int
  9 #define MAXN 100005+10
 10 #define pb push_back
 11 #define INF 0x7f7f7f7f
 12 #define
oo 0x7f7f7f7f7f7f7f7f 13 #define pil pair<int,ll> 14 #define mp make_pair 15 #define ft first 16 #define sc second 17 using namespace std; 18 int read(){ 19 int x=0,f=1;char ch=getchar(); 20 while(ch<0||ch>9){if(-==ch)f=-1;ch=getchar();} 21 while(ch>=0&&ch<=
9){x=x*10+ch-0;ch=getchar();} 22 return x*f; 23 } 24 struct E{ 25 int from,to,cap,flow; 26 ll cost; 27 E(int x=0,int y=0,int c=0,int f=0,ll w=0LL){ 28 from=x,to=y,cap=c,flow=f,cost=w; 29 } 30 }; 31 int N,M,s,t=MAXN-1; 32 vector<E> es; 33 vector<int> G[MAXN];
34 void add(int x,int y,int cap,ll cost){ 35 es.pb(E(x,y,cap,0,cost)); 36 es.pb(E(y,x,0,0,-cost)); 37 M=es.size(); 38 G[x].pb(M-2),G[y].pb(M-1); 39 } 40 int p[MAXN],a[MAXN]; 41 ll d[MAXN]; 42 int b[MAXN]; 43 bool SPFA(int &flow,ll &cost){ 44 p[s]=0,a[s]=INF; 45 memset(d,0x7f,sizeof(d)); 46 d[s]=0; 47 memset(b,0,sizeof(b)); 48 b[s]=1; 49 queue<int> q; 50 q.push(s); 51 while(!q.empty()){ 52 int x=q.front();q.pop();b[x]=0; 53 for(rint i=0;i<G[x].size();i++){ 54 E &e=es[G[x][i]]; 55 if(e.cap>e.flow&&d[e.to]>d[x]+e.cost){ 56 p[e.to]=G[x][i]; 57 a[e.to]=min(a[x],e.cap-e.flow); 58 d[e.to]=d[x]+e.cost; 59 if(!b[e.to]){ 60 b[e.to]=1; 61 q.push(e.to); 62 } 63 } 64 } 65 } 66 if(oo==d[t]){ 67 return 0; 68 } 69 flow+=a[t]; 70 cost+=a[t]*d[t]; 71 for(rint i=t;i!=s;i=es[p[i]].from){ 72 es[p[i]].flow+=a[t]; 73 es[p[i]^1].flow-=a[t]; 74 } 75 return 1; 76 } 77 pil MaxfMinc(){ 78 int flow=0; 79 ll cost=0LL; 80 while(SPFA(flow,cost)); 81 return mp(flow,cost); 82 } 83 int n,m; 84 int P[45],T[45][105],now[105]; 85 int sum,L; 86 int cook[MAXN],cnt[MAXN]; 87 int id[105][805]; 88 int work(int x,int y){ 89 add(id[x][y],t,1,0); 90 for(rint i=1;i<=n;i++){ 91 add(L+i,id[x][y],1,T[i][x]*y); 92 } 93 } 94 void init(){ 95 n=read(),m=read(); 96 for(rint i=1;i<=n;i++){ 97 P[i]=read(); 98 sum+=P[i]; 99 } 100 for(rint i=1;i<=n;i++){ 101 for(rint j=1;j<=m;j++){ 102 T[i][j]=read(); 103 } 104 } 105 L=m*sum; 106 int idx=0; 107 for(rint i=1;i<=m;i++){ 108 for(rint j=1;j<=sum;j++){ 109 id[i][j]=++idx; 110 cook[idx]=i,cnt[idx]=j; 111 } 112 } 113 for(rint i=1;i<=n;i++){ 114 add(s,L+i,P[i],0); 115 } 116 for(rint i=1;i<=m;i++){ 117 work(i,1); 118 now[i]=1; 119 } 120 } 121 void solve(){123 int flow=0;ll cost=0LL; 124 while(SPFA(flow,cost)){ 125 if(flow==sum){ 126 printf("%lld\n",cost); 127 break; 128 } 129 int x=es[p[t]].from; 130 now[cook[x]]++; 131 work(cook[x],now[cook[x]]); 132 } 133 } 134 int main() 135 { 136 // freopen("data.in","r",stdin); 137 init(); 138 solve(); 139 return 0; 140 }

洛谷P3980 [NOI2008]誌願者招募