POJ-1149 PIGS---最大流+建图

题目链接:

https://vjudge.net/problem/POJ-1149

题目大意:

M个猪圈,N个顾客,每个顾客有一些的猪圈的钥匙,只能购买这些有钥匙的猪圈里的猪,而且要买一定数量的猪,每个猪圈有已知数量的猪,
但是猪圈可以重新打开,将猪的个数,重新分配,以达到卖出的猪的数量最多。

思路:

难点在于如何构造容量网络

(1)将顾客看做出源点和汇点之外的结点,另外增加源点s和汇点t

(2)源点和每个猪圈的第一个用户连边,边权是猪圈中猪的数目

(3)若有重边,将权合并

(4)顾客j紧跟在顾客i之后打开某个猪圈,则边<i, j>是正无穷,因为如果顾客j紧跟在i之后,那么流到i的猪可以自由分配该j,所以设置为INF。

(5)每个顾客可汇点之间的连边,边权就是自己希望,买到的猪的数目

构建好容量网络之后,就用模板就OK啦

传送门:网络流学习

 1 #include<iostream>
 2 #include<vector>
 3 #include<cstring>
 4 #include<cstdio>
 5 #include<queue>
 6 using namespace std;
 7 const int INF = 0x3f3f3f3f;
 8 const int maxn = 100 + 10;//顾客的数目
 9 const int maxm = 1000 + 10;//猪圈的数目
10 
11 struct edge
12 {
13     int u, v, c, f;
14     edge(int u, int v, int c, int f):u(u), v(v), c(c), f(f){}
15 };
16 vector<edge>e;
17 vector<int>G[maxn];
18 int a[maxn], p[maxn];
19 int m;
20 void init(int n)
21 {
22     for(int i = 0; i <= n; i++)
23         G[i].clear();
24     e.clear();
25 }
26 void addedge(int u, int v, int c)
27 {
28     e.push_back(edge(u, v, c, 0));
29     e.push_back(edge(v, u, 0, 0));//反向边
30     m = e.size();
31     G[u].push_back(m - 2);
32     G[v].push_back(m - 1);
33 }
34 int Maxflow(int s, int t)
35 {
36     int flow = 0;
37     for(;;)
38     {
39         memset(a, 0, sizeof(a));//每次找增广路的每个点的流量
40         queue<int>q;
41         q.push(s);
42         a[s] = INF;
43         while(!q.empty())
44         {
45             int u = q.front();
46             q.pop();
47             for(int i = 0; i < G[u].size(); i++)
48             {
49                 edge& now = e[G[u][i]];
50                 int v = now.v;
51                 if(!a[v] && now.c > now.f)//v点还没有流到并且这条边还没满
52                 {
53                     p[v] = G[u][i];//反向记录边
54                     a[v] = min(a[u], now.c - now.f);//到达v点的水量取决于边剩余的容量和u点的水量
55                     q.push(v);
56                 }
57             }
58             if(a[t])break;//已到达终点
59         }
60         if(!a[t])break;//已经找不到增广路
61         for(int u = t; u != s; u = e[p[u]].u)
62         {
63             e[p[u]].f += a[t];
64             e[p[u]^1].f -= a[t];
65         }
66         flow += a[t];
67     }
68     return flow;
69 }
70 int pig[maxm];//每个猪圈猪的数目
71 int last[maxm];//每个猪圈的前一个顾客的序号
72 int Map[maxn][maxn];//顾客顾客之间的边,有重边,先用数组记录
73 int main()
74 {
75     int n, m;
76     cin >> m >> n;
77     for(int i = 1; i <= m; i++)cin >> pig[i];
78     int s = 0, t = n + 1;//设置源点和汇点
79     int d, x;
80     for(int i = 1; i <= n; i++)//顾客编号
81     {
82         cin >> d;
83         for(int j = 0; j < d; j++)
84         {
85             cin >> x;//猪圈编号
86             if(last[x] == 0)//猪圈的第一个顾客
87                 addedge(s, i, pig[x]);
88             else addedge(last[x], i, INF);//顾客i紧接着顾客last[x]后面打开猪圈x
89             last[x] = i;
90         }
91         cin >> x;//到汇点的边的权值
92         addedge(i, t, x);
93     }
94     cout<<Maxflow(s, t)<<endl;
95     return 0;
96 }

 

posted @ 2018-04-16 20:06  _努力努力再努力x  阅读(185)  评论(0编辑  收藏  举报