洛谷P3980 [NOI2008]志愿者招募

Posted white_hat_hacker

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了洛谷P3980 [NOI2008]志愿者招募相关的知识,希望对你有一定的参考价值。

动态加边网络流

  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]志愿者招募的主要内容,如果未能解决你的问题,请参考以下文章

P3980 [NOI2008] 志愿者招募(费用流)

NOI 2008 志愿者招募 题解 (神奇费用流)

[Noi2008]志愿者招募

费用流NOI2008志愿者招募

BZOJ1061: [Noi2008]志愿者招募

[NOI2008]志愿者招募