您的位置:首页 > 理论基础 > 计算机网络

[模版] 网络流最大流、费用流

2015-02-04 12:24 281 查看
反向边作用讨论:/article/1750135.html

我理解的很有限,希望有研究过的人能给我评论指导。

代码:

By:Rujia Liu

数据结构和比较函数(用于排序):

struct Edge {
int from, to, cap, flow;
};

bool operator < (const Edge& a, const Edge& b) {
return a.from < b.from || (a.from == b.from && a.to < b.to);
}


最大流:

1.Dinic

struct Dinic {
int n, m, s, t;
vector<Edge> edges;    // 边数的两倍
vector<int> G[maxn];   // 邻接表,G[i][j]表示结点i的第j条边在e数组中的序号
bool vis[maxn];         // BFS使用
int d[maxn];           // 从起点到i的距离
int cur[maxn];        // 当前弧指针

void ClearAll(int n) {
for(int i = 0; i < n; i++) G[i].clear();
edges.clear();
}

void ClearFlow() {
for(int i = 0; i < edges.size(); i++) edges[i].flow = 0;
}

void AddEdge(int from, int to, int cap) {
edges.push_back((Edge){from, to, cap, 0});
edges.push_back((Edge){to, from, 0, 0});
m = edges.size();
G[from].push_back(m-2);
G[to].push_back(m-1);
}

bool BFS() {
memset(vis, 0, sizeof(vis));
queue<int> Q;
Q.push(s);
vis[s] = 1;
d[s] = 0;
while(!Q.empty()) {
int x = Q.front(); Q.pop();
for(int i = 0; i < G[x].size(); i++) {
Edge& e = edges[G[x][i]];
if(!vis[e.to] && e.cap > e.flow) {
vis[e.to] = 1;
d[e.to] = d[x] + 1;
Q.push(e.to);
}
}
}
return vis[t];
}

int DFS(int x, int a) {
if(x == t || a == 0) return a;
int flow = 0, f;
for(int& i = cur[x]; i < G[x].size(); i++) {
Edge& e = edges[G[x][i]];
if(d[x] + 1 == d[e.to] && (f = DFS(e.to, min(a, e.cap-e.flow))) > 0) {
e.flow += f;
edges[G[x][i]^1].flow -= f;
flow += f;
a -= f;
if(a == 0) break;
}
}
return flow;
}

int Maxflow(int s, int t) {
this->s = s; this->t = t;
int flow = 0;
while(BFS()) {
memset(cur, 0, sizeof(cur));
flow += DFS(s, INF);
}
return flow;
}

vector<int> Mincut() { // call this after maxflow
vector<int> ans;
for(int i = 0; i < edges.size(); i++) {
Edge& e = edges[i];
if(vis[e.from] && !vis[e.to] && e.cap > 0) ans.push_back(i);
}
return ans;
}

void Reduce() {
for(int i = 0; i < edges.size(); i++) edges[i].cap -= edges[i].flow;
}
};
ISAP:

struct ISAP {
int n, m, s, t;
vector<Edge> edges;
vector<int> G[maxn];   // 邻接表,G[i][j]表示结点i的第j条边在e数组中的序号
bool vis[maxn];        // BFS使用
int d[maxn];           // 从起点到i的距离
int cur[maxn];        // 当前弧指针
int p[maxn];          // 可增广路上的上一条弧
int num[maxn];        // 距离标号计数

void AddEdge(int from, int to, int cap) {
edges.push_back((Edge){from, to, cap, 0});
edges.push_back((Edge){to, from, 0, 0});
m = edges.size();
G[from].push_back(m-2);
G[to].push_back(m-1);
}

bool BFS() {
memset(vis, 0, sizeof(vis));
queue<int> Q;
Q.push(t);
vis[t] = 1;
d[t] = 0;
while(!Q.empty()) {
int x = Q.front(); Q.pop();
for(int i = 0; i < G[x].size(); i++) {
Edge& e = edges[G[x][i]^1];
if(!vis[e.from] && e.cap > e.flow) {
vis[e.from] = 1;
d[e.from] = d[x] + 1;
Q.push(e.from);
}
}
}
return vis[s];
}

void ClearAll(int n) {
this->n = n;
for(int i = 0; i < n; i++) G[i].clear();
edges.clear();
}

void ClearFlow() {
for(int i = 0; i < edges.size(); i++) edges[i].flow = 0;
}

int Augment() {
int x = t, a = INF;
while(x != s) {
Edge& e = edges[p[x]];
a = min(a, e.cap-e.flow);
x = edges[p[x]].from;
}
x = t;
while(x != s) {
edges[p[x]].flow += a;
edges[p[x]^1].flow -= a;
x = edges[p[x]].from;
}
return a;
}

int Maxflow(int s, int t, int need) {
this->s = s; this->t = t;
int flow = 0;
BFS();
memset(num, 0, sizeof(num));
for(int i = 0; i < n; i++) num[d[i]]++;
int x = s;
memset(cur, 0, sizeof(cur));
while(d[s] < n) {
if(x == t) {
flow += Augment();
if(flow >= need) return flow;
x = s;
}
int ok = 0;
for(int i = cur[x]; i < G[x].size(); i++) {
Edge& e = edges[G[x][i]];
if(e.cap > e.flow && d[x] == d[e.to] + 1) { // Advance
ok = 1;
p[e.to] = G[x][i];
cur[x] = i; // 注意
x = e.to;
break;
}
}
if(!ok) { // Retreat
int m = n-1; // 初值注意
for(int i = 0; i < G[x].size(); i++) {
Edge& e = edges[G[x][i]];
if(e.cap > e.flow) m = min(m, d[e.to]);
}
if(--num[d[x]] == 0) break;
num[d[x] = m+1]++;
cur[x] = 0; // 注意
if(x != s) x = edges[p[x]].from;
}
}
return flow;
}

vector<int> Mincut() { // call this after maxflow
BFS();
vector<int> ans;
for(int i = 0; i < edges.size(); i++) {
Edge& e = edges[i];
if(!vis[e.from] && vis[e.to] && e.cap > 0) ans.push_back(i);
}
return ans;
}

void Reduce() {
for(int i = 0; i < edges.size(); i++) edges[i].cap -= edges[i].flow;
}

void print() {
printf("Graph:\n");
for(int i = 0; i < edges.size(); i++)
printf("%d->%d, %d, %d\n", edges[i].from, edges[i].to , edges[i].cap, edges[i].flow);
}
};


费用流:

struct MCMF {
int n, m, s, t;
vector<Edge> edges;
vector<int> G[maxn];
int inq[maxn];         // 是否在队列中
int d[maxn];           // Beintman-Ford
int p[maxn];           // 上一条弧
int a[maxn];           // 可改进量

void init(int n) {
this->n = n;
for(int i = 0; i < n; i++) G[i].clear();
edges.clear();
}

void AddEdge(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 BellmanFord(int s, int t, int& ans) {
for(int i = 0; i < n; i++) d[i] = INF;
memset(inq, 0, sizeof(inq));
d[s] = 0; inq[s] = 1; p[s] = 0; a[s] = INF;

queue<int> Q;
Q.push(s);
while(!Q.empty()) {
int u = Q.front(); Q.pop();
inq[u] = 0;
for(int i = 0; i < G[u].size(); i++) {
Edge& e = edges[G[u][i]];
if(e.cap > e.flow && d[e.to] > d[u] + e.cost) {
d[e.to] = d[u] + e.cost;
p[e.to] = G[u][i];
a[e.to] = min(a[u], e.cap - e.flow);
if(!inq[e.to]) { Q.push(e.to); inq[e.to] = 1; }
}
}
}
if(d[t] > 0) return false;
ans += (int)d[t] * (int)a[t];
int u = t;
while(u != s) {
edges[p[u]].flow += a[t];
edges[p[u]^1].flow -= a[t];
u = edges[p[u]].from;
}
return true;
}

// 需要保证初始网络中没有负权圈
int Mincost(int s, int t) {
int cost = 0;
while(BellmanFord(s, t, cost));
return cost;
}
};


zkw费用流(By:HZWER)

bool spfa()
{
memset(mark,0,sizeof(mark));
for(int i=0;i<=T;i++)d[i]=-1;
int head=0,tail=1;
q[0]=T;mark[T]=1;d[T]=0;
while(head!=tail)
{
int now=q[head];head++;if(head==605)head=0;
for(int i=last[now];i;i=e[i].next)
if(e[i^1].v&&d[now]+e[i^1].c>d[e[i].to])
{
d[e[i].to]=d[now]+e[i^1].c;
if(!mark[e[i].to])
{
mark[e[i].to]=1;
q[tail++]=e[i].to;
if(tail==605)tail=0;
}
}
mark[now]=0;
}
return d[0]!=-1;
}
int dfs(int x,int f)
{
mark[x]=1;
if(x==T)return f;
int w,used=0;
for(int i=last[x];i;i=e[i].next)
if(d[e[i].to]==d[x]-e[i].c&&e[i].v&&!mark[e[i].to])
{
w=f-used;
w=dfs(e[i].to,min(w,e[i].v));
ans+=w*e[i].c;
e[i].v-=w;e[i^1].v+=w;
used+=w;if(used==f)return f;
}
return used;
}
void zkw()
{
while(spfa())
{
mark[T]=1;
while(mark[T])
{
memset(mark,0,sizeof(mark));
dfs(0,inf);
}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: