BZOJ 1391: [Ceoi2008]order
Description
有一些任务,需要用到一些机器,可以买可以租,问最大获利.
Solution
网络流.
最大权闭合子图模型.
建图很简单就是S->机器,机器->任务,任务->T.
如果没有租用的话,中间的是INF,不会割掉,加上租用就把容量变成租用的价格即可.
这样求出来的割就是最小损失了,用总数减去即可.
Code
/************************************************************** Problem: 1391 User: BeiYu Language: C++ Result: Accepted Time:3864 ms Memory:55972 kb ****************************************************************/ #include <bits/stdc++.h> using namespace std; #define debug(a) cout<<#a<<"="<<a<<" " const int INF = 0x3fffffff; const int N = 3650; const int M = 3000500; inline int in(int x=0,char ch=getchar()) { while(ch>'9' || ch<'0') ch=getchar(); while(ch>='0' && ch<='9') x=x*10+ch-'0',ch=getchar();return x; } int n,m; int val[N],ned[N],c[N]; struct NetWork { vector< int > g[N]; struct Edge { int fr,to,fl; }edge[M]; int s,t,cnte,flow,tot; int cur[N],d[N],p[N]; void AddEdge(int fr,int to,int fl) { g[fr].push_back(cnte),edge[cnte++]=(Edge){ fr,to,fl }; g[to].push_back(cnte),edge[cnte++]=(Edge){ to,fr,0 }; } void Build() { n=in(),m=in(); s=0,t=2*m+n+6; for(int i=1,x;i<=n;i++) { for(x=in(),tot+=x,AddEdge(i,t,x),x=in();x--;) { int idx=in(),cost=in(); AddEdge(n+idx,i,cost); } } for(int i=1;i<=m;i++) { c[i]=in(); int x=n+i; AddEdge(s,x,c[i]); } // for(int i=1;i<=m;i++) cout<<c1[i]<<" "<<c2[i]<<endl; } int BFS() { queue< int > q; memset(d,0xff,sizeof(d)); q.push(s),d[s]=1; for(int x;!q.empty();) { x=q.front(),q.pop(); for(int i=0,lm=g[x].size(),v;i<lm;i++) if(edge[g[x][i]].fl && d[(v=edge[g[x][i]].to)]==-1) { d[v]=d[x]+1,q.push(v); } }return d[t]!=-1; } void Dinic() { // debug(s),debug(t)<<endl; for(int u,k;BFS();) { // cout<<"qwq"<<endl;debug(flow)<<endl; for(memset(cur,0,sizeof(cur)),u=s,k=0;;) { if(u==t) { int mine=0,minf=INF; for(int i=0;i<k;i++) if(edge[p[i]].fl<minf) minf=edge[p[i]].fl,mine=i; for(int i=0;i<k;i++) edge[p[i]].fl-=minf,edge[p[i]^1].fl+=minf; // for(int i=0;i<k;i++) cout<<edge[p[i]].fr<<"-->";cout<<endl; // debug(minf)<<endl; k=mine,flow+=minf,u=edge[p[mine]].fr; } for(int &i=cur[u],lm=g[u].size(),v;i<lm;i++) if(edge[g[u][i]].fl && d[(v=edge[g[u][i]].to)]==d[u]+1) break; if(cur[u]<(int)g[u].size()) { p[k++]=g[u][cur[u]],u=edge[g[u][cur[u]]].to; } else { if(!k) break; d[u]=-1,u=edge[p[--k]].fr; } } } } int Maxflow() { flow=0,tot=0; Build(); Dinic(); return tot-flow; } }py; int main() { cout<<py.Maxflow()<<endl; return 0; }