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

关于有容量下界的网络可行流问题解决的学习笔记 ZOJ 2314 ZOJ 3229 HDU 3157

2013-08-06 20:15 441 查看
白书二代上提到了无源无汇有容量下界网络可行流和有容量下界网络的s-t最大/最小流问题。

但是由于本人智商捉鸡,觉得LRJ大神写的似乎不是很好理解,所以只能找一些题目来帮助自己理解理解了。

这里直说方法,证明。。。不会。

1.无源无汇有容量下界可行流

这个问题的解法在周源的那个论文里讲的很清楚了。

对于每条边,都有一个容量下界b和一个容量上界c,那么这条边实际的可行流量只有c-b,剩下的b必须满流。

对每个点i,求a = sum(流向它的下界流)-sum(从它流出的下界流量)

若a>0,从源点0连一条到i的容量为a的边

若a<0,从i连一条到汇点n+1的容量为-a的边

(我觉得其实这里都是为求自由流做的准备)

然后求一次最大流,若所有从源点出发的点都满流,则有可行流,每条边的可行流为求最大流后的实际流量flow+该边的流量下界b

题目:ZOJ 2314

代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
#include <queue>
#include <algorithm>
#define maxn 60
#define INF 1000000000
using namespace std;
struct Edge{
int from,to,cap,flow;
};
struct Dinic{
int n,m,s,t;
vector<Edge> edges;
vector<int> G[maxn];
bool vis[maxn];
int d[maxn];
int cur[maxn];
void ClearAll(int n){
for(int i = 0;i < n;i++)    G[i].clear();
edges.clear();
}
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;
}
};
Dinic g;
int in[maxn];
int main()
{
int n,m,s,t,SS,TT,a,b,cir;
char from[10],to[10];
while(scanf("%d%d",&n,&m),n+m){
memset(in,0,sizeof(in));
g.ClearAll(n+5);
s = 0,t = n+1,SS = t+1,TT = SS+1;
int sum = 0;
for(int i = 0;i < m;i++){
scanf("%s%s%d",from,to,&cir);
if(from[0] == '+')  a = s;
else    sscanf(from,"%d",&a);
if(to[0] == '-')    b = t;
else    sscanf(to,"%d",&b);
in[a] -= cir;in[b] += cir;
g.AddEdge(a,b,INF-cir);
}
for(int i = 0;i <= t;i++){
if(in[i] > 0)   g.AddEdge(SS,i,in[i]),sum += in[i];
if(in[i] < 0)   g.AddEdge(i,TT,-in[i]);
}

int flow1 = g.Maxflow(SS,TT);
g.AddEdge(t,s,INF);
int flow2 = g.Maxflow(SS,TT);
if(flow1 + flow2 != sum)    printf("impossible\n");
else{
int e = g.edges.size() - 2;
printf("%d\n",g.edges[e].flow);
}
}
return 0;
}


View Code
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐