您的位置:首页 > 其它

线性规划与单纯型法/最小(大)费用最大流题目泛做

2016-04-12 19:54 453 查看
题目1 NOI2008 志愿者招募

题解什么的后补吧,先上代码。

#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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: