线性规划与单纯型法/最小(大)费用最大流题目泛做
2016-04-12 19:54
453 查看
题目1 NOI2008 志愿者招募
题解什么的后补吧,先上代码。
1221
题目5 SDOI2016
算法讨论:
最大费用最大流。用SPFA求最长路。初值设为-inf.然后自己一直炸是因为inf开得太小了。
题解什么的后补吧,先上代码。
#include <iostream> #include <cstdlib> #include <cstring> #include <cstdio> #include <algorithm> #include <vector> #include <queue> using namespace std; const int N = 2000 + 10; const int inf = 0x3f3f3f3f; struct Edge { int from, to, cap, flow, cost; Edge(int u=0, int v=0, int cp=0, int fw=0, int ct=0): from(u), to(v), cap(cp), flow(fw), cost(ct) {} }; int n, a, b, f, fa, fb, d , ans; struct MCMF { int n, m; int dis , pre , que[N << 1], a ; bool vis ; vector <int> G ; vector <Edge> edges; void insert(int from, int to, int cap, int cost) { edges.push_back(Edge(from, to, cap, 0, cost)); edges.push_back(Edge(to, from, 0, 0, -cost)); m = edges.size(); G[from].push_back(m - 2); G[to].push_back(m -1); } bool bfs(int s, int t, int &flow, int &cost) { int head = 1, tail = 1; for(int i = 0; i <= n; ++ i) dis[i] = inf; memset(vis, false, sizeof vis); dis[s] = 0; pre[s] = 0; a[s] = inf; vis[s] = true; que[head] = s; while(head <= tail) { int x = que[head]; vis[x] = false; for(int i = 0; i < (signed) G[x].size(); ++ i) { Edge &e = edges[G[x][i]]; if(e.cap > e.flow && dis[e.to] > dis[x] + e.cost) { dis[e.to] = dis[x] + e.cost; pre[e.to] = G[x][i]; a[e.to] = min(a[x], e.cap - e.flow); if(!vis[e.to]) { vis[e.to] = true; que[++ tail] = e.to; } } } ++ head; } if(dis[t] == inf) return false; flow += a[t]; cost += a[t] * dis[t]; int now = t; while(now != s) { edges[pre[now]].flow += a[t]; edges[pre[now] ^ 1].flow -= a[t]; now = edges[pre[now]].from; } return true; } void mcmf(int s, int t, int &cost) { int flow = 0; while(bfs(s, t, flow, cost)); } }net; int main() { int tp; scanf("%d%d%d%d%d%d", &n, &a, &b, &f, &fa, &fb); tp = n << 1; for(int i = 1; i <= n; ++ i) { scanf("%d", &d[i]); net.insert(0, i, d[i], 0); net.insert(i + n, tp + 1, d[i], 0); } for(int i = 1; i <= n; ++ i) { if(i + 1 <= n) net.insert(i, i + 1, inf, 0); if(i + a + 1 <= n) net.insert(i, i + n + a + 1, inf, fa); if(i + b + 1 <= n) net.insert(i, i + n + b + 1, inf, fb); net.insert(0, i + n, inf, f); } net.n = tp + 1; net.mcmf(0, tp + 1, ans); printf("%d\n", ans); return 0; }
1221
题目5 SDOI2016
算法讨论:
最大费用最大流。用SPFA求最长路。初值设为-inf.然后自己一直炸是因为inf开得太小了。
#include <cstdlib> #include <iostream> #include <cstring> #include <cstdio> #include <algorithm> #include <vector> #include <cmath> using namespace std; const int N = 400 + 5; typedef long long ll; const ll inf = (1LL<<60); int n, T; int aa , b , c ; struct Edge { int from, to; ll cap, flow, cost; Edge(int u=0, int v=0, ll cap=0, ll flow=0, ll cost=0): from(u), to(v), cap(cap), flow(flow), cost(cost) {} }; struct MCMF { int n, mm, s, t; int pre , que[N << 3]; ll a , dis ; bool vis ; vector <Edge> edges; vector <int> G ; void add(int from, int to, ll cap, ll cost) { edges.push_back(Edge(from, to, cap, 0, cost)); edges.push_back(Edge(to, from, 0, 0, -cost)); mm = edges.size(); G[from].push_back(mm - 2); G[to].push_back(mm - 1); } bool bfs(ll &fw, ll &ct) { int head = 1, tail = 1; for(int i = 0; i <= n; ++ i) { dis[i] = -inf; vis[i] = false; } dis[s] = 0; que[head] = s; vis[s] = true; pre[s] = 0; a[s] = inf; while(head <= tail) { int x = que[head]; vis[x] = false; for(int i = 0; i < (signed) G[x].size(); ++ i) { Edge &e = edges[G[x][i]]; if(e.cap > e.flow && dis[e.to] < dis[x] + e.cost) { dis[e.to] = dis[x] + e.cost; pre[e.to] = G[x][i]; a[e.to] = min(a[x], e.cap - e.flow); if(!vis[e.to]) { vis[e.to] = true; que[++ tail] = e.to; } } } ++ head; } if(dis[t] == -inf) return false; ll tmp = ct, tfw = fw; fw += a[t]; ct += 1LL * a[t] * dis[t]; if(ct < 0) { fw = tfw; fw += tmp / (-dis[t]); printf("%lld\n", fw / 2); exit(0); } int now = t; while(now != s) { edges[pre[now]].flow += a[t]; edges[pre[now] ^ 1].flow -= a[t]; now = edges[pre[now]].from; } return true; } void mcmf(int s, int t) { this->s = s; this->t = t; ll fw = 0, ct = 0; while(bfs(fw, ct)); printf("%lld\n", fw / 2); } }net; bool check(int nv) { if(nv == 1) return false; if(nv == 2) return true; int m = (int) sqrt(nv + 0.5); for(int i = 2; i <= m; ++ i) if(nv % i == 0) return false; return true; } #define stone_ee int main() { #ifndef stone_ freopen("menci_pair.in", "r", stdin); freopen("menci_pair.out", "w", stdout); #endif scanf("%d", &n); net.n = (n << 1) + 1; T = (n << 1) + 1; for(int i = 1; i <= n; ++ i) scanf("%d", &aa[i]); for(int i = 1; i <= n; ++ i) scanf("%d", &b[i]); for(int i = 1; i <= n; ++ i) scanf("%d", &c[i]); for(int i = 1; i <= n; ++ i) { net.add(0, i, b[i], 0); net.add(i + n, T, b[i], 0); } for(int i = 1; i <= n; ++ i) for(int j = 1; j <= n; ++ j) if(i != j) if(aa[i] % aa[j] == 0) if(check(aa[i] / aa[j])) { net.add(i, j + n, inf, 1LL * c[j] * c[i]); net.add(j, i + n, inf, 1LL * c[j] * c[i]); } net.mcmf(0, T); #ifndef stone_ fclose(stdin); fclose(stdout); #endif return 0; }
相关文章推荐
- 导航与定位框架---28
- comet4j的使用
- 剑指offer系列之39:数组中只出现1次的数字
- leetcode 19 Remove Nth Node From End of List
- UNIX操作系统中Shell程序设计
- 【导航条滚动透明】一个分类搞定
- j2EE
- acFileStorage equivalent
- FaceBook推出的Android图片加载库-Fresco
- <<Effective C++>读书笔记(四)
- Linux 25 周年,九问 Linus
- jQuery操作DOM元素
- poj3468线段树区间更新
- 《Head First设计模式》 - 观察者模式
- Gulp入门
- Linux内核分析 读书笔记 (第四章)
- JavaScript之数组
- 第六周 项目2-带武器的游戏角色
- 独木舟上的旅行
- Objective-C 字符串NSString