hdu 4322 Candy 【最大费用最大流】
2017-03-29 14:08
429 查看
Problem:
有n个糖果和m个孩子,给出每个孩子是否喜欢某个糖果,如果把孩子孩子喜欢的糖果给了孩子,那个孩子会增加k个glad值,否则只增加一个,问能否有一个方案使得所有的孩子的glad值都不小于b[i]?
Solution:
用最大费用最大流在能使glad值最大的情况下求出最优匹配的糖果个数,然后看剩下的glad值能否由剩下的糖果满足。
超级源点和糖果间容量为1,费用为0.
孩子和喜欢的糖果之间容量为1,费用为0。
孩子和汇点之间容量为b[i]/k,费用为k。
如果b[i]不能整除k,则再添加一条边容量为1,费用为b[i]%k。
note:
1. 有负权边要使用spfa,保存图可以使用rev和revv和reve。
2. 提前建立一条容量为0的反向边以方便反向查找。
有n个糖果和m个孩子,给出每个孩子是否喜欢某个糖果,如果把孩子孩子喜欢的糖果给了孩子,那个孩子会增加k个glad值,否则只增加一个,问能否有一个方案使得所有的孩子的glad值都不小于b[i]?
Solution:
用最大费用最大流在能使glad值最大的情况下求出最优匹配的糖果个数,然后看剩下的glad值能否由剩下的糖果满足。
超级源点和糖果间容量为1,费用为0.
孩子和喜欢的糖果之间容量为1,费用为0。
孩子和汇点之间容量为b[i]/k,费用为k。
如果b[i]不能整除k,则再添加一条边容量为1,费用为b[i]%k。
note:
1. 有负权边要使用spfa,保存图可以使用rev和revv和reve。
2. 提前建立一条容量为0的反向边以方便反向查找。
#include<cstdio> #include<iostream> #include<sstream> #include<cstdlib> #include<cmath> #include<cctype> #include<string> #include<cstring> #include<algorithm> #include<stack> #include<queue> #include<set> #include<map> #include<ctime> #include<vector> #include<fstream> #include<list> using namespace std; typedef long long ll; typedef unsigned long long ull; typedef pair<int, int> P; #define ms(s) memset(s,0,sizeof(s)) const double PI = 3.141592653589; const int INF = 0x3fffffff; struct Edge { int to, cap, cost, rev; Edge(int too, int capp, int costt, int revv) : to(too), cap(capp), cost(costt), rev(revv) {} }; vector<vector<Edge> > G; int st, en; int dist[30]; int prevv[30], preve[30]; void add_edge(int from, int to, int cap, int cost) { G[from].push_back(Edge(to, cap, cost, G[to].size())); G[to].push_back(Edge(from, 0, -cost, G[from].size()-1)); } int min_max_flow(int n) {//the quantity of points. int ans = 0;//return the greatest flow. while(true) {//spfa fill(dist, dist+n, INF); dist[st] = 0; queue<int> q; q.push(st); while(!q.empty()) { int u = q.front(); q.pop(); for(int i = 0; i < G[u].size(); i++) { int to = G[u][i].to; if(G[u][i].cap > 0 && dist[u] + G[u][i].cost < dist[to]) { dist[to] = dist[u] + G[u][i].cost; prevv[to] = u; preve[to] = i; q.push(to); } } } if(dist[en] == INF) break; else { int f = INF; for(int pr = en; pr != st; pr = prevv[pr]) f = min(f, G[prevv[pr]][preve[pr]].cap); ans += f; for(int pr = en; pr != st; pr = prevv[pr]) { Edge &e = G[prevv[pr]][preve[pr]]; e.cap -= f; G[pr][e.rev].cap += f; } } } return ans; } int main() { // freopen("/Users/really/Documents/code/input","r",stdin); // freopen("/Users/really/Documents/code/output","w",stdout); ios::sync_with_stdio(false); int t; cin >> t; for(int idx = 1; idx <= t; idx++) { G.clear(); int b[20]; int n, m, k; cin >> n >> m >> k; st = 0; en = n+m+1; G.resize(n+m+2); for(int i = 1; i <= m; i++) cin >> b[i]; for(int i = 1; i <= n; i++)//connect start point to each candy. add_edge(st, i, 1, 0); for(int i = 1; i <= m; i++) { for(int j = 1; j <= n; j++) { int t; cin >> t; if(t == 1) add_edge(j, n+i, 1, 0); } } for(int i = 1; i <= m; i++) { add_edge(n+i, en, b[i]/k, -k); if(b[i]%k != 0) add_edge(n+i, en, 1, -(b[i]%k)); } int now = min_max_flow(n+m+2); int res = 0; for(int i = 1; i <= m; i++) { for(int j = 0; j < G[n+i].size(); j++) { if(G[n+i][j].to == en) { if(G[n+i][j].cap > 0) res -= G[n+i][j].cap*G[n+i][j].cost; } } } if(n-now >= res) cout << "Case #" << idx << ": YES" << endl; else cout << "Case #" << idx << ": NO" << endl; } return 0; }
相关文章推荐
- hdu 4322 Candy(最大费用流)2012 Multi-University Training Contest 3
- hdu 4322 Candy 最大费用最大流
- HDU 4322 Candy (最大费用最大流)经典
- HDU 4322 Candy 最大费用流
- HDU 4322 Candy 最大费用流+巧妙建图
- HDU 4322 最大费用最大流 2012 Multi-University Training Contest 3
- hdoj 4322 Candy 【最大费用最大流】【经典题目】【最大流时 维护费用的最大效益】
- hdu 4322(最大费用最大流)
- hdu-4322-Candy-费用流
- hdu 4322(最大费用最大流)
- hdu 4322 最大费用最大流
- hdu 4322 Candy 费用流
- hdu 4322 Candy 费用流
- hdu 4322 最大费用流
- hdu 4322 Candy 【多校3】【费用流】
- HDU 4322 Candy
- hdu-4780-Candy Factory--费用流
- HDU 3376 && 2686 方格取数 最大和 费用流裸题
- hdu 2686 Matrix && hdu 3367 Matrix Again (最大费用最大流)
- HDU 4322 Candy