最大流与最小割C++实现2——深度优先搜索
2014-03-13 16:17
519 查看
刚刚写了一个最大流与最小割的的广度优先搜索实现!后来我发现只要用栈来替代队列来储存标记的顶点,便实现了深度优先搜索.
但要注意此时应该先把后向边压入栈!以下是我的代码实现:
#include<iostream>
#include<stack>
#include<vector>
#include<cmath>
#include<stdio.h>
#define MAX 999999
using namespace std;
class Graph
{
private:
struct vertex
{
int num ; //编号
int flag ; //正向或负向标记
int ver ; //来自哪条边
int flow; //流量标记
vector<int>f_edge ; //前向边
vector<int>u ; //前向边的流量
vector<int>b_edge; //后向边
vector<int>x ; //后向边的流量
vertex(int num,int flag,int flow):num(num),flag(flag),flow(flow){ // u.push_back(0); x.push_back(0);
}
};
int N; //边数
vector<vertex>v;
public:
Graph(int n):N(n)
{
for(int i=0;i<=n;i++)
{
vertex tmp(i,0,0);
v.push_back(tmp);
for(int j=0;j<=n;j++)
{
v[i].u.push_back(0);
v[i].x.push_back(0);
}
}
v[1].flag=-1; //源点标记为-1
v[1].flow=MAX;
}
void Edge_flow(int i,int j,int flow)
{ v[i].f_edge.push_back(j);
v[i].u[j]=flow;
v[j].b_edge.push_back(i);
}
int Max_flow()
{
stack<int>S;
S.push(1);
int max_f=0;
while(!S.empty())
{
int i=S.top();S.pop();
int l=v[i].flow;
for(unsigned int k=0;k<v[i].b_edge.size();k++)
{
int j=v[i].b_edge[k];
if(v[j].flag==0)
{
int r=v[j].x[i];
if(r>0)
{
l=min(l,r);
v[j].flag=-1;v[j].ver=i;v[j].flow=l;
S.push(j);
}
}
}
for(unsigned int k=0;k<v[i].f_edge.size();k++)
{
int j=v[i].f_edge[k];
if(v[j].flag==0)
{
int r=v[i].u[j]-v[i].x[j];
if(r>0)
{
l=min(l,r);
v[j].flag=1;v[j].ver=i;v[j].flow=l;
S.push(j);
}
}
}
if(v
.flag!=0)
{
int j=N;
max_f+=l;
cout<<"One of the path is :";
while(j!=1)
{
cout<<j<<" from ";
int k=v[j].ver;
if(v[j].flag==1)
v[k].x[j]+=l;
if(v[j].flag==-1)
v[j].x[k]-=l;
j=k;
}
cout<<1<<" and the flow is "<<l<<endl;
while(!S.empty())
S.pop();
for(int i=2;i<=N;i++)
v[i].flag=0;
S.push(1);
}
}
return max_f;
}
void Min_cut()
{
for(int i=1;i<N;i++)
{
if(v[i].flag!=0)
{
for(unsigned int k=0;k<v[i].f_edge.size();k++)
{
int j=v[i].f_edge[k];
if(v[j].flag==0&&v[i].flag!=0)
cout<<"("<<i<<","<<j<<")"<<"; ";
}
}
}
}
};
int main()
{
freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
int ver;
while(cin>>ver)
{
Graph G(ver);
int edge;
cin>>edge;
int i,j,flow;
while(edge--)
{
cin>>i>>j>>flow;
G.Edge_flow(i,j,flow);
}
cout<<"The max_flow is :"<<G.Max_flow()<<endl;
cout<<"One of the min_cut is :";
G.Min_cut();
cout<<endl;
}
fclose(stdin);
// fclose(stdout);
return 0;
}
接下来是in.txt里的测试数据,如下:
下面是out.txt的输出结果,如下
可以看到,测试数据也是没有问题的,这说明我的这种替代是合理的;再根据分析,深度优先搜索效率也是O(nm^2)的,空间消耗是O(n^2).
但要注意此时应该先把后向边压入栈!以下是我的代码实现:
#include<iostream>
#include<stack>
#include<vector>
#include<cmath>
#include<stdio.h>
#define MAX 999999
using namespace std;
class Graph
{
private:
struct vertex
{
int num ; //编号
int flag ; //正向或负向标记
int ver ; //来自哪条边
int flow; //流量标记
vector<int>f_edge ; //前向边
vector<int>u ; //前向边的流量
vector<int>b_edge; //后向边
vector<int>x ; //后向边的流量
vertex(int num,int flag,int flow):num(num),flag(flag),flow(flow){ // u.push_back(0); x.push_back(0);
}
};
int N; //边数
vector<vertex>v;
public:
Graph(int n):N(n)
{
for(int i=0;i<=n;i++)
{
vertex tmp(i,0,0);
v.push_back(tmp);
for(int j=0;j<=n;j++)
{
v[i].u.push_back(0);
v[i].x.push_back(0);
}
}
v[1].flag=-1; //源点标记为-1
v[1].flow=MAX;
}
void Edge_flow(int i,int j,int flow)
{ v[i].f_edge.push_back(j);
v[i].u[j]=flow;
v[j].b_edge.push_back(i);
}
int Max_flow()
{
stack<int>S;
S.push(1);
int max_f=0;
while(!S.empty())
{
int i=S.top();S.pop();
int l=v[i].flow;
for(unsigned int k=0;k<v[i].b_edge.size();k++)
{
int j=v[i].b_edge[k];
if(v[j].flag==0)
{
int r=v[j].x[i];
if(r>0)
{
l=min(l,r);
v[j].flag=-1;v[j].ver=i;v[j].flow=l;
S.push(j);
}
}
}
for(unsigned int k=0;k<v[i].f_edge.size();k++)
{
int j=v[i].f_edge[k];
if(v[j].flag==0)
{
int r=v[i].u[j]-v[i].x[j];
if(r>0)
{
l=min(l,r);
v[j].flag=1;v[j].ver=i;v[j].flow=l;
S.push(j);
}
}
}
if(v
.flag!=0)
{
int j=N;
max_f+=l;
cout<<"One of the path is :";
while(j!=1)
{
cout<<j<<" from ";
int k=v[j].ver;
if(v[j].flag==1)
v[k].x[j]+=l;
if(v[j].flag==-1)
v[j].x[k]-=l;
j=k;
}
cout<<1<<" and the flow is "<<l<<endl;
while(!S.empty())
S.pop();
for(int i=2;i<=N;i++)
v[i].flag=0;
S.push(1);
}
}
return max_f;
}
void Min_cut()
{
for(int i=1;i<N;i++)
{
if(v[i].flag!=0)
{
for(unsigned int k=0;k<v[i].f_edge.size();k++)
{
int j=v[i].f_edge[k];
if(v[j].flag==0&&v[i].flag!=0)
cout<<"("<<i<<","<<j<<")"<<"; ";
}
}
}
}
};
int main()
{
freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
int ver;
while(cin>>ver)
{
Graph G(ver);
int edge;
cin>>edge;
int i,j,flow;
while(edge--)
{
cin>>i>>j>>flow;
G.Edge_flow(i,j,flow);
}
cout<<"The max_flow is :"<<G.Max_flow()<<endl;
cout<<"One of the min_cut is :";
G.Min_cut();
cout<<endl;
}
fclose(stdin);
// fclose(stdout);
return 0;
}
接下来是in.txt里的测试数据,如下:
6
7
1 2 2
1 4 3
2 5 3
2 3 5
4 3 1
3 62
5 64
4
5
1 2 100
1 3 10
2 3 100
3 4 10
2 4 1000
6
7
1 2 5
1 3 6
2 5 2
2 4 4
3 4 7
4 68
5 64
6
8
1 2 2
1 3 7
2 4 3
2 5 4
3 4 4
3 5 2
4 61
5 65
下面是out.txt的输出结果,如下
One of the path is :6from 5 from 2 from 1 and the flow is 2
One of the path is :6from 3 from 4 from 1 and the flow is 1
The max_flow is :3
One of the min_cut is :(1,2); (4,3);
One of the path is :4 from 2 from 1 and the flow is 100
One of the path is :4 from 3 from 1 and the flow is 10
The max_flow is :110
One of the min_cut is :(1,2); (1,3);
One of the path is :6from 5 from 2 from 1 and the flow is 2
One of the path is :6from 4 from 2 from 1 and the flow is 3
One of the path is :6from 4 from 3 from 1 and the flow is 3
One of the path is :6from 4 from 3 from 1 and the flow is 2
The max_flow is :10
One of the min_cut is :(2,5); (4,6);
One of the path is :6from 4 from 2 from 1 and the flow is 1
One of the path is :6from 5 from 2 from 1 and the flow is 1
One of the path is :6from 5 from 3 from 1 and the flow is 2
One of the path is :6from 5 from 2 from 4 from 3 from 1 and the flow is 1
The max_flow is :5
One of the min_cut is :(1,2); (3,5); (4,6);
可以看到,测试数据也是没有问题的,这说明我的这种替代是合理的;再根据分析,深度优先搜索效率也是O(nm^2)的,空间消耗是O(n^2).
相关文章推荐
- Java实现图:邻接矩阵表示、深度优先搜索、广度优先搜索、无向图的最小生成树
- 图的深度优先(非递归)、广度优先、最小生成树的C++实现
- C++ 图的深度搜索广度搜索和最小生成树代码实现
- [C++ 实现最大值优先队列和最小值优先队列]
- C++深度优先搜索的实现方法
- 基于C++ STL图的邻接表表示及深度、广度搜索实现
- C++实现图的邻接矩阵存储和广度、深度优先遍历实例分析
- 深度优先搜索DFS(邻接表实现)
- C/C++: 邻接表图深度优先搜索
- 用C++实现最小公倍数和最大公约数
- C++实现的带最大最小线程数的线程池(基于ACE)
- leetcode 124. Binary Tree Maximum Path Sum 最大路径和 + DFS深度优先搜索
- C/C++代码实现图(有向图)的深度,广度优先遍历
- 用最大堆实现优先队列(c++)
- 最大堆、最小堆C++实现
- C++实现优先队列——最小堆,d路堆及配对堆
- 深度优先搜索的实现
- 【图的实现】“广度优先搜索遍历”以及“深度优先搜索遍历”必会
- 深度优先搜索和广度优先搜索的代码实现
- C++利用vector容器实现最大最小元问题