标签:des style blog http color strong
Time Limit: 1000MS | Memory Limit: 10000K | |
Total Submissions: 15747 | Accepted: 7034 |
Description
Input
Output
Sample Input
3 3 3 1 10 2 1 2 2 2 1 3 3 1 2 6
Sample Output
7
题意:有一养猪场,有m个猪圈,给出每个猪圈中猪的数量,来了n个买主,每个买主手中有若干猪圈的钥匙,且给出每个买主想要买多少猪。问,最多能卖出多少头猪。
思路:网络流最大流问题。第二个最大流的题目,建图比较麻烦。下面说说我的建图方式。
1. 我们将所有买主当成结点。那么除了买主外,还需两个点,一个源点一个汇点。我称之为supers,supert.
2. 将源点与每个猪圈的第一个买主建边,如有重复的可并,实现的时候我是用flag[]数组标记钥匙是否第一次出现,如果是则可建边,否则看 step 3.
3. 如果不是第一次出现,说明在这个买主之前有买主买猪。这时,在这两个买主之间建边,权值(也就是容量)为INF。实现时是用nodes[]数组记录前一个买主。
4. 将每个买主连向汇点。容量为次买主要买的猪数。
我的建图方式就是这样。。建完图后用Dinic 求解。
1 /*====================================================================== 2 * Author : kevin 3 * Filename : PIGS.cpp 4 * Creat time : 2014-07-20 15:11 5 * Description : 6 ========================================================================*/ 7 #include <iostream> 8 #include <algorithm> 9 #include <cstdio> 10 #include <cstring> 11 #include <queue> 12 #include <cmath> 13 #define clr(a,b) memset(a,b,sizeof(a)) 14 #define MaxM 1005 15 #define MaxN 105 16 #define INF 0x7f7f7f7f 17 using namespace std; 18 struct Edge{ 19 int from,to,cap,flow; 20 }; 21 vector<Edge> edges; 22 vector<int>G[MaxN]; 23 bool vis[MaxN]; 24 int d[MaxN],cur[MaxN],supers,supert; 25 bool BFS() 26 { 27 clr(vis,0); 28 queue<int>Q; 29 Q.push(supers); 30 d[supers] = 0; 31 vis[supers] = 1; 32 while(!Q.empty()){ 33 int x = Q.front(); Q.pop(); 34 int len = G[x].size(); 35 for(int i = 0; i < len; i++){ 36 Edge& e = edges[G[x][i]]; 37 if(!vis[e.to] && e.cap > e.flow){ 38 vis[e.to] = 1; 39 d[e.to] = d[x]+1; 40 Q.push(e.to); 41 } 42 } 43 } 44 return vis[supert]; 45 } 46 int DFS(int x,int a) 47 { 48 if(x == supert || a == 0) return a; 49 int flow = 0,f; 50 int len = G[x].size(); 51 for(int& i = cur[x]; i < len; i++){ 52 Edge& e = edges[G[x][i]]; 53 if(d[x] + 1 == d[e.to] && (f = DFS(e.to,min(a,e.cap-e.flow))) > 0){ 54 e.flow += f; 55 edges[G[x][i]^1].flow -= f; 56 flow += f; 57 a -= f; 58 if(!a) break; 59 } 60 } 61 return flow; 62 } 63 void AddEdge(int from,int to,int cap) 64 { 65 edges.push_back((Edge){from,to,cap,0}); 66 edges.push_back((Edge){to,from,0,0}); 67 int m = edges.size(); 68 G[from].push_back(m-2); 69 G[to].push_back(m-1); 70 } 71 int Dinic(int s,int t) 72 { 73 int flow = 0; 74 while(BFS()){ 75 clr(cur,0); 76 flow += DFS(s,INF); 77 } 78 return flow; 79 } 80 int main(int argc,char *argv[]) 81 { 82 int n,m,keys,k; 83 int pighome[MaxM], //猪圈中猪的数量 84 nodes[MaxM], //前一个买主的信息 85 flag[MaxM]; //标记是否是买猪第一人 86 while(scanf("%d%d",&n,&m)!=EOF){ 87 clr(pighome,0); 88 clr(nodes,0); 89 clr(flag,0); 90 supers = 0; 91 supert = m+1; 92 for(int i = 1; i <= n; i++) 93 scanf("%d",&pighome[i]); 94 for(int i = 1; i <= m; i++){ 95 int sum = 0; 96 scanf("%d",&keys); //钥匙的数量 97 for(int j = 0; j < keys; j++){ 98 scanf("%d",&k); 99 if(!flag[k]){ 100 sum += pighome[k]; //合并重边 101 flag[k] = 1; 102 } 103 else{ 104 if(nodes[k]){ 105 AddEdge(nodes[k],i,INF); //建买主之间的边 106 } 107 } 108 nodes[k] = i; 109 } 110 AddEdge(supers,i,sum); //添加合并后的边 111 int buy; 112 scanf("%d",&buy); 113 AddEdge(i,supert,buy); //建立买主到汇点的边 114 } 115 int ans = Dinic(supers,supert); 116 printf("%d\n",ans); 117 edges.clear(); 118 for(int i = 0; i < MaxN; i++) 119 G[i].clear(); 120 } 121 return 0; 122 }
poj 1149 -- PIGS,布布扣,bubuko.com
标签:des style blog http color strong
原文地址:http://www.cnblogs.com/ubuntu-kevin/p/3856340.html