Poj 1149(最大流建图
题目:有m个猪圈,n个顾客,n个顾客依次到达,每个顾客可以打开若干个猪圈,可以选择给当前顾客卖不超过b头猪,并且当前打开的猪圈中的猪可以任意调整。问最多能卖多少猪。
思路:首先是直观的建图,由于有顺序关系,所以考虑给每个顾客建一层图,那么节点数就是n×m,这个数目太大。可以注意到原图中有很多OO权的边,比如可以相互转移的猪圈之间的边。这些边是可以化简的。具体化简思路见http://ycool.com/post/zhhrrm6#pic1
化简之后的图即为:原点向每个猪圈的第一个顾客连边,流量为猪圈里猪的数目。每个顾客向下一个到达这个猪圈的顾客连无穷的边。顾客向汇点连边。
理解:首先这么建图体现了顺序性,每个顾客的可选的猪的数目与前一个到猪圈的顾客选了多少有关。分配方面,每个顾客都和所有的来源连边了,并且流过来的流量是前面决策之后的。
化简的重点是来源,去向。后到的顾客可选的是前面的顾客选剩下的。
/* * @author: Cwind */ ///#pragma comment(linker, "/STACK:102400000,102400000") #include <iostream> #include <map> #include <algorithm> #include <cstdio> #include <cstring> #include <cstdlib> #include <vector> #include <queue> #include <stack> #include <functional> #include <set> #include <cmath> using namespace std; #define IOS std::ios::sync_with_stdio (false);std::cin.tie(0) #define pb push_back #define PB pop_back #define bk back() #define fs first #define se second #define sq(x) (x)*(x) #define eps (1e-6) #define IINF (1<<29) #define LINF (1ll<<59) #define INF (1000000000) #define FINF (1e3) #define clr(x) memset((x),0,sizeof (x)); typedef long long ll; typedef unsigned long long ull; typedef pair<int,int> pii; typedef pair<ll,ll> P; const int maxv=100000; struct EDGE{ int to,cap,rev; EDGE(int t,int c,int r):to(t),cap(c),rev(r){} }; vector<EDGE> G[maxv]; void addedge(int from,int to,int cap){///加边 G[from].pb(EDGE(to,cap,G[to].size())); G[to].pb(EDGE(from,0,G[from].size()-1)); } int s=maxv-1; int t=maxv-2; int level[maxv]; queue<int> Q; void bfs(int s){////bfs出分层图 memset(level,-1,sizeof level); level[s]=0; Q.push(s); while(!Q.empty()){ int v=Q.front();Q.pop(); for(int i=0;i<G[v].size();i++){ EDGE &e=G[v][i]; if(e.cap>0&&level[e.to]==-1){ level[e.to]=level[v]+1; Q.push(e.to); } } } } int iter[maxv]; int dfs(int v,int t,int f){///dfs寻找增广路径 if(v==t) return f; for(int &i=iter[v];i<G[v].size();i++){ EDGE &e=G[v][i]; if(e.cap>0&&level[e.to]>level[v]){ int d=dfs(e.to,t,min(f,e.cap)); if(d>0){ e.cap-=d; G[e.to][e.rev].cap+=d; return d; } } } return 0; } int dinic(int s,int t){///dinic算法求解最大流 int flow=0; for(;;){ bfs(s); if(level[t]==-1) return flow; memset(iter,0,sizeof iter); int f; while((f=dfs(s,t,IINF))>0) flow+=f; } return 0; } const int maxn=2000; vector<int> cus[maxn]; int pig[maxn]; int need[maxn]; int n,m; void build(){ for(int i=1;i<=m;i++){ if(cus[i].size()){ addedge(s,cus[i][0],pig[i]); } for(int j=1;j<cus[i].size();j++){ addedge(cus[i][j-1],cus[i][j],INF); } } for(int i=1;i<=n;i++){ addedge(i,t,need[i]); } } int main(){ freopen("/home/slyfc/CppFiles/in","r",stdin); cin>>m>>n; for(int i=1;i<=m;i++){ scanf("%d",&pig[i]); } for(int i=1;i<=n;i++){ int a; scanf("%d",&a); for(int j=0;j<a;j++){ int k; scanf("%d",&k); cus[k].pb(i); } scanf("%d",&need[i]); } build(); printf("%d",dinic(s,t)); return 0; }
时间: 2024-10-23 09:01:21